SlideShare a Scribd company logo
1 of 193
Download to read offline
Ruby on Rails
Hellow


Bart     André   Dirkjan
Hellow


Bart     André   Dirkjan
Laptops, apple
Development is more than coding
Ruby on Rails
Ruby on Rails
Language



           Ruby on Rails
Language



           Ruby on Rails
                       Framework
What are we doing today?

     1   Ruby basics


    2    Rails terminology / vision


     3   Build something simple
What are we doing today?

     1   Ruby basics
                st ....
          ut fir
         B
    2    Rails terminology / vision


     3   Build something simple
Very simple example
Address Book
■   Generate a new Rails Application
■   Generate some stuff
■   Prepare the database
■   Start the application
■   View application and be excited!
Terminal
Terminal
 $ rails address_book
   create
   create   app/controllers
   create   app/helpers
   create   app/models
   create   app/views/layouts
   create   test/functional
   create   test/integration
    ...
   create   log/server.log
   create   log/production.log
   create   log/development.log
   create   log/test.log
Terminal
 $ rails address_book
   create
   create   app/controllers
   create   app/helpers
   create   app/models
   create   app/views/layouts
   create   test/functional
   create   test/integration
    ...
   create   log/server.log
   create   log/production.log
   create   log/development.log
   create   log/test.log


 $ cd address_book
Terminal
Terminal
$ ./script/generate scaffold person name:string
 exists    app/controllers/
 exists    app/helpers/
 create    app/views/people
 ...
./script/destroy to undo
Terminal
$ ./script/generate scaffold person name:string
 exists    app/controllers/
 exists    app/helpers/
 create    app/views/people
 ...
Terminal
Terminal
 $ rake db:migrate
   == 00000000000000 CreatePeople: migrating =============
   -- create_table(:people)
      -> 0.0177s
   == 00000000000000 CreatePeople: migrated (0.0180s) ====
rake db:rollback to undo
Terminal
 $ rake db:migrate
   == 00000000000000 CreatePeople: migrating =============
   -- create_table(:people)
      -> 0.0177s
   == 00000000000000 CreatePeople: migrated (0.0180s) ====
⌘N
Terminal
Terminal
 $ cd address_book
Terminal
 $ cd address_book

 $ ./script/server
 =>   Booting Mongrel
 =>   Rails 2.1.0 application starting on http://0.0.0.0:3000
 =>   Call with -d to detach
 =>   Ctrl-C to shutdown server
 **   Starting Mongrel listening at 0.0.0.0:3000
 **   Starting Rails with development environment...
 **   Rails loaded.
 **   Loading any Rails specific GemPlugins
 **   Signals ready. TERM => stop. USR2 => restart.
 **   Rails signals registered.
 **   Mongrel 1.1.4 available at 0.0.0.0:3000
 **   Use CTRL-C to stop.
http://localhost:3000/
http://localhost:3000/people
It all seems like magic...
You feel lost...
This is normal. It will pass.
Close all
Ruby
The basics
■   Objects
■   Variables
■   Methods
■   Inheritance & Modules
■   Blocks
Objects, variables & methods
Objects, variables & methods

  class Person

    attr_accessor :name

    def insults(other, object=quot;cowquot;)
      quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
    end

  end
class name
Objects, variables & methods

  class Person

    attr_accessor :name

    def insults(other, object=quot;cowquot;)
      quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
    end

  end
class name
     Objects, variables & methods
instance
variable
       class Person

         attr_accessor :name

         def insults(other, object=quot;cowquot;)
           quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
         end

       end
class name
     Objects, variables & methods
instance
variable
       class Person                              method
         attr_accessor :name

         def insults(other, object=quot;cowquot;)
           quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
         end

       end
class Person

  attr_accessor :name

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end




               Console: using a class
class Person

  attr_accessor :name

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end




               Console: using a class

                >> andre = Person.new

                >> andre.name = ‘Andre’
class Person

  attr_accessor :name

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end




               Console: using a class

                >> andre = Person.new

                >> andre.name = ‘Andre’

                >> bart = Person.new

                >> bart.name = ‘Bart’
class Person

  attr_accessor :name

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end




               Console: using a class

                >> andre = Person.new

                >> andre.name = ‘Andre’

                >> bart = Person.new

                >> bart.name = ‘Bart’

                >> bart.insults(andre, “dog”)
                “Bart thinks Andre is a stupid dog!”
Inheritance

 class Person
   attr_accessor :name
 end

 class Student < Person

   def insults(other, object=quot;cowquot;)
     quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
   end

 end
Inheritance
                            Student inherits
 class Person
   attr_accessor :name        from person
 end

 class Student < Person

   def insults(other, object=quot;cowquot;)
     quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
   end

 end
Modules
Person


Woman        Man
Driving skill



    Person


Woman        Man
Driving skill


    Person


Woman             Man
Person

              Driving skill


Woman        Man
Person


Woman              Man
          Driving skill

        Andre             Bart
Modules
module Insulting

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end

class Person

  attr_accessor :name
  include Insulting

end
Creates an
Modules                 ‘Insulting’ module
module Insulting

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end

class Person

  attr_accessor :name
  include Insulting

end
Creates an
              Modules                 ‘Insulting’ module
              module Insulting

                def insults(other, object=quot;cowquot;)
                  quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
                end
  Person
              end
classes can
              class Person
   ‘Insult’
                attr_accessor :name
                include Insulting

              end
Creates an
              Modules                 ‘Insulting’ module
              module Insulting

                def insults(other, object=quot;cowquot;)
                  quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
                end
  Person
              end
classes can
              class Person                   class Robot
   ‘Insult’
                attr_accessor :name            attr_accessor :name
                include Insulting              include Insulting

              end                            end

                     Everyone can
                      insult now!
module Insulting

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end

class Person
  attr_accessor :name
end




            Console: extending on the fly
module Insulting

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end

class Person
  attr_accessor :name
end




            Console: extending on the fly

              >> andre = Person.new

              >> andre.name = “Andre”

              >> andre.extend(Insulting)
              nil
module Insulting

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end

class Person
  attr_accessor :name
end




            Console: extending on the fly

              >> andre = Person.new

              >> andre.name = “Andre”

              >> andre.extend(Insulting)
              nil

              >> andre.insults(bart)
              “Andre thinks Bart is a stupid cow!”
module Insulting

  def insults(other, object=quot;cowquot;)
    quot;#{name} thinks #{other.name} is a stupid #{object}!quot;
  end

end

class Person
  attr_accessor :name
end




            Console: extending on the flyWe could also extend
                                             an entire class like this!
              >> andre = Person.new

              >> andre.name = “Andre”

              >> andre.extend(Insulting)
              nil

              >> andre.insults(bart)
              “Andre thinks Bart is a stupid cow!”
Man
                Person
Driving skill

 Insulting

Gardening
Man
                                   Person
Driving skill

 Insulting

Gardening        How do we test if
                this man can insult?
Duck-typing
If it walks like a duck and quacks like a
duck, it's a duck.
     — Lisa Graves
andre.respond_to?(:insult)
Person


Woman    Man
Person


Woman    Man     Driver
Person

        Driving skill


Woman    Man
Blocks
class Person

  attr_accessor :name

end




           Console: using blocks
class Person

  attr_accessor :name

end




           Console: using blocks

               >> people
               [<#Person:0x00 @name=”Andre”>,<#Person:0x00 @name=”Bart”>]
class Person

  attr_accessor :name

end




           Console: using blocks

               >> people
               [<#Person:0x00 @name=”Andre”>,<#Person:0x00 @name=”Bart”>]


               >> people.map{ |item| “#{item.name} is kewl” }
               [“Andre is kewl”, “Bart is kewl”]
class Person

  attr_accessor :name

end




           Console: using blocks also have: select, reject and inject to
                               We
                                             work with collections!
               >> people
               [<#Person:0x00 @name=”Andre”>,<#Person:0x00 @name=”Bart”>]


               >> people.map{ |item| “#{item.name} is kewl” }
               [“Andre is kewl”, “Bart is kewl”]
You know Ruby!
You know Ruby! Sorta...
You know Ruby! Sorta...
PART II
Convention
over configuration
railsenvy.com
VIEW



MVC
MODEL
               CONTROLLER
Models
Talk to the database, contain business logic



             Controllers
Provide the glue, prepare data when needed



                 Views
       Show the content to the user
You are not a beautiful and unique
snowflake. You are the same decaying
organic matter as everyone else, and we
are all a part of the same compost pile.
  — Tyler Durden, Fight Club
SEE              CHANGE



      RESOURCE




ADD              REMOVE
Show me
      something

SEE                CHANGE



        RESOURCE




ADD                REMOVE
Show me
              something

 SEE                       CHANGE



                RESOURCE

Add someone


ADD                        REMOVE
Show me
              something

 SEE                             CHANGE

                      Change
                     something
                RESOURCE

Add someone


ADD                              REMOVE
Show me
              something

 SEE                             CHANGE

                      Change
                     something
                RESOURCE

Add someone
                  Delete stuff
ADD                              REMOVE
CREATE          UPDATE


CRUD     READ            DELETE
CREATE          UPDATE


CRUD     READ            DELETE
CREATE            UPDATE


CRUD       READ            DELETE


  HTTP !
POST
CREATE            UPDATE


CRUD       READ            DELETE


  HTTP !
POST
CREATE            UPDATE


CRUD       READ
            GET
                           DELETE


  HTTP !
POST              PUT
CREATE            UPDATE


CRUD       READ
            GET
                           DELETE


  HTTP !
POST              PUT
CREATE            UPDATE


CRUD       READ
            GET
                           DELETE
                           DELETE

  HTTP !
http://www.snowflake.org/people/1
UNIVERSAL



URI
                       IDE
                        NT
                         IFI
                            ER
            RESOURCE
ADD   POST   /people
ADD   POST   /people
SEE   GET    /people
ADD    POST   /people
SEE    GET    /people
CHANGE PUT    /people/1
ADD      POST     /people
SEE      GET      /people
CHANGE   PUT      /people/1
REMOVE   DELETE   /people/1
REPRESENTATIONAL   STATE   TRANSFER



REST
RAILS CONTROLLER ACTIONS
RAILS CONTROLLER ACTIONS



INDEX            NEW               EDIT


SHOW           CREATE          UPDATE



              DESTROY
Building something...
Let’s get started
Choose a subject
2 hrs
 IT WON’T BE ENOUGH...
First 15 minutes
■   You should have an idea
■   You should have a rough sketch
■   You should have thought of what models you need
■   You should think of their relation to each other
■   Pick an pair of models with a 1..* relationship

                          1
               Student          *      Beer
Next 10 minutes
■   You should have a new rails app
    $ rails [your_app_name]


■   You should have generated the models
    $ ./script/generate scaffold [model_name] [attr]:[type


    type = string, text, integer, float, boolean,
           date, time, datetime

    reserved attrs => type, version
mate .
App structure
-   app
    -   models
    -   views
    -   controllers
-   config
-   db
    -   migrate
App structure
-   app
    -   models        the model files
    -   views
    -   controllers
-   config
-   db
    -   migrate
App structure
-   app
    -   models        the model files
    -   views         templates for HTML
    -   controllers
-   config
-   db
    -   migrate
App structure
-   app
    -   models        the model files
    -   views         templates for HTML
    -   controllers   the controller files
-   config
-   db
    -   migrate
App structure
-   app
    -   models        the model files
    -   views         templates for HTML
    -   controllers   the controller files
-   config            basic configuration
-   db
    -   migrate
App structure
-   app
    -   models        the model files
    -   views         templates for HTML
    -   controllers   the controller files
-   config            basic configuration
-   db
    -   migrate       database migrations
Migrations
db/migrate/00000000_create_people.rb
 class CreatePeople < ActiveRecord::Migration
   def self.up
     create_table :people do |t|
       t.string :name

       t.timestamps
     end
   end

   def self.down
     drop_table :people
   end
 end
Create a ‘People’
db/migrate/00000000_create_people.rb
                               table on UP
 class CreatePeople < ActiveRecord::Migration
   def self.up
     create_table :people do |t|
       t.string :name

       t.timestamps
     end
   end

   def self.down
     drop_table :people
   end
 end
Create a ‘People’
           db/migrate/00000000_create_people.rb
With a ‘Name’                                      table on UP
   String class CreatePeople < ActiveRecord::Migration
                def self.up
                  create_table :people do |t|
                    t.string :name

                    t.timestamps
                  end
                end

                def self.down
                  drop_table :people
                end
              end
Create a ‘People’
           db/migrate/00000000_create_people.rb
With a ‘Name’                                      table on UP
   String class CreatePeople < ActiveRecord::Migration
                def self.up
                  create_table :people do |t|
                    t.string :name

                    t.timestamps
                  end
                end

                def self.down
                  drop_table :people
                                         And some time-stamps:
                end
              end
                                          created_at & updated_at
Create a ‘People’
           db/migrate/00000000_create_people.rb
With a ‘Name’                                      table on UP
   String class CreatePeople < ActiveRecord::Migration
                def self.up
                  create_table :people do |t|
                    t.string :name

                    t.timestamps
                  end
                end

                def self.down
                  drop_table :people
                                         And some time-stamps:
                end
              end
                                          created_at & updated_at
 Drop the
 table on
 DOWN
Relationships
1
             Student               *   Beer




app/models/student.rb
 class Student < ActiveRecord::Base

   has_many :beers

 end




app/models/beer.rb
 class Beer < ActiveRecord::Base

   belongs_to :student

 end
db/migrate/00000000_create_beers.rb
 class CreateBeers < ActiveRecord::Migration
   def self.up
     create_table :beers do |t|
       t.string :brand
       t.references :student
       t.timestamps
     end
   end

   def self.down
     drop_table :beers
   end
 end
db/migrate/00000000_create_beers.rb
                          Add a reference to Student
                                           (:student_id)
 class CreateBeers < ActiveRecord::Migration
   def self.up
     create_table :beers do |t|
       t.string :brand
       t.references :student
       t.timestamps
     end
   end

   def self.down
     drop_table :beers
   end
 end
Next 10 minutes
■   You should update your model files when needed
    belongs_to, has_many, has_one, has_many :through


■   You should add references to migrations
    t.references :student
Next 5 minutes
■   You should have migrated the database
    $ rake db:migrate


■   You should have a running server
    $ ./script/server


■   You should see your app
    $ open http://localhost:3000
Routes
config/routes.rb

 ActionController::Routing::Routes.draw do |map|
   map.resources :students
   map.resources :beers

   # You can have the root of your site routed with map.root
   # map.root :controller => quot;welcomequot;

   map.connect ':controller/:action/:id'
   map.connect ':controller/:action/:id.:format'
 end
config/routes.rb
                                   Routes for each resource
 ActionController::Routing::Routes.draw do |map|
   map.resources :students
   map.resources :beers

   # You can have the root of your site routed with map.root
   # map.root :controller => quot;welcomequot;

   map.connect ':controller/:action/:id'
   map.connect ':controller/:action/:id.:format'
 end
config/routes.rb
                                   Routes for each resource
 ActionController::Routing::Routes.draw do |map|
   map.resources :students
   map.resources :beers

   # You can have the root of your site routed with map.root
   # map.root :controller => quot;welcomequot;

   map.connect ':controller/:action/:id'
   map.connect ':controller/:action/:id.:format'
 end
                       Remove # and
                 change :controller to ‘students’
ADD      POST     /people
SEE      GET      /people
CHANGE   PUT      /people/1
REMOVE   DELETE   /people/1
SEE    GET        /people/1
CHANGE GET        /people/1/edit
ADD    GET        /people/new
Next 5 minutes
■   Change the routes
    Uncomment & choose default controller


■   Remove ‘public/index.html’
    $ rm public/index.html


■   Refresh your browser
ActiveRecord
One class per table

One instance per row
One class per utable
            b  tes
                at tri
           sare
      lumn
   Co
One instance per row
Student.find_by_name(“Andre”)

Student.find(:first, :conditions => [“name = ?”,”Andre”])
Student.find_all_by_name(“Andre”)

Student.find(:all, :conditions => [“name = ?”,”Andre”])
andre = Student.new( :name => “Andre” )
                andre.save
Next 10 minutes
■   You should play with your app, create some instances
    We created a student named “Andre”


■   You should start a console
    $ ./script/console


■   You should build a few relationships using the console
    >> andre = Student.find_by_name(“Andre”)

    >> beer = andre.beers.create( :brand => “Grolsch” )

    >> beer.student.name
       ”Andre”
Views
app/views/beer/new.html.erb


  <h1>New beer</h1>

  <% form_for(@beer) do |f| %>
    <%= f.error_messages %>

    <p>
      <%= f.label :brand %><br />
      <%= f.text_field :brand %>
    </p>
    <p>
      <%= f.submit quot;Createquot; %>
    </p>
  <% end %>

  <%= link_to 'Back', beers_path %>
Title of the page
app/views/beer/new.html.erb


  <h1>New beer</h1>

  <% form_for(@beer) do |f| %>
    <%= f.error_messages %>

    <p>
      <%= f.label :brand %><br />
      <%= f.text_field :brand %>
    </p>
    <p>
      <%= f.submit quot;Createquot; %>
    </p>
  <% end %>

  <%= link_to 'Back', beers_path %>
Title of the page
         app/views/beer/new.html.erb
A form
           <h1>New beer</h1>

           <% form_for(@beer) do |f| %>
             <%= f.error_messages %>

             <p>
               <%= f.label :brand %><br />
               <%= f.text_field :brand %>
             </p>
             <p>
               <%= f.submit quot;Createquot; %>
             </p>
           <% end %>

           <%= link_to 'Back', beers_path %>
Title of the page
         app/views/beer/new.html.erb
A form
           <h1>New beer</h1>

           <% form_for(@beer) do |f| %>
             <%= f.error_messages %>

             <p>
               <%= f.label :brand %><br />
               <%= f.text_field :brand %>      Show errors messages if
             </p>
             <p>                                something goes wrong
               <%= f.submit quot;Createquot; %>
             </p>
           <% end %>

           <%= link_to 'Back', beers_path %>
Title of the page
          app/views/beer/new.html.erb
A form
               <h1>New beer</h1>

               <% form_for(@beer) do |f| %>
                 <%= f.error_messages %>

                 <p>
                   <%= f.label :brand %><br />
                   <%= f.text_field :brand %>      Show errors messages if
                 </p>
                 <p>                                something goes wrong
                   <%= f.submit quot;Createquot; %>
Some fields      </p>
               <% end %>
and a button
               <%= link_to 'Back', beers_path %>
Title of the page
          app/views/beer/new.html.erb
A form
               <h1>New beer</h1>

               <% form_for(@beer) do |f| %>
                 <%= f.error_messages %>

                 <p>
                   <%= f.label :brand %><br />
                   <%= f.text_field :brand %>      Show errors messages if
                 </p>
                 <p>                                something goes wrong
                   <%= f.submit quot;Createquot; %>
Some fields      </p>
               <% end %>
and a button
               <%= link_to 'Back', beers_path %>




                                                          Back link
app/views/beer/new.html.erb


  <h1>New beer</h1>

  <% form_for(@beer) do |f| %>
    <%= f.error_messages %>

    <p>
      <%= f.label :brand %><br />
      <%= f.text_field :brand %>
    </p>
    <p>
      <%= f.submit quot;Createquot; %>
    </p>
  <% end %>

  <%= link_to 'Back', beers_path %>
app/views/beer/new.html.erb
 <h1>New beer</h1>

 <% form_for(@beer) do |f| %>
   <%= f.error_messages %>

   <p>
     <%= f.label :brand %><br />
     <%= f.text_field :brand %>
   </p>

   <p>
     <%= f.label :student %><br />
     <%= f.collection_select :student_id, Student.find(:all), :id, :name %>
   </p>

   <p>
     <%= f.submit quot;Createquot; %>
   </p>
 <% end %>

 <%= link_to 'Back', beers_path %>
Next 15 minutes
■   Should be able to set a belongs_to relationship
    collection_select


■   Relationship must be able to be set on new and
    existing objects
    Change both the edit and new view!


■   Test that it really works!


    Try to edit the show view to represent the object relationship so
    another human understands it!
Validations
    This is a behaviour...
Validations
    This is a behaviour...
BDD
BEHAVIOUR   DRIVEN   DEVELOPMENT
How should a student behave?
Student
■   should never have a blank name
Terminal
Terminal
 $ ./script/generate rspec
   create   lib/tasks/rspec.rake
   create   script/autospec
   create   script/spec
   create   script/spec_server
   create   spec
   create   spec/rcov.opts
   create   spec/spec.opts
   create   spec/spec_helper.rb
   create   stories
   create   stories/all.rb
   create   stories/helper.rb
Terminal
 $ ./script/generate rspec
   create   lib/tasks/rspec.rake
   create   script/autospec
   create   script/spec
   create   script/spec_server
   create   spec
   create   spec/rcov.opts
   create   spec/spec.opts
   create   spec/spec_helper.rb
   create   stories
   create   stories/all.rb
   create   stories/helper.rb
 $ ./script/generate rspec_model student
Terminal
 $ ./script/generate rspec
   create   lib/tasks/rspec.rake
   create   script/autospec
   create   script/spec
   create   script/spec_server
   create   spec
   create   spec/rcov.opts
   create   spec/spec.opts
   create   spec/spec_helper.rb
   create   stories
   create   stories/all.rb
   create   stories/helper.rb
 $ ./script/generate rspec_model student

 $ rake db:migrate RAILS_ENV=test
spec/models/student_spec.rb
 require File.dirname(__FILE__) + '/../spec_helper'

 describe Student do

  it quot;should never have a blank namequot; do
   no_name = Student.new( :name => “” )
   no_name.should_not be_valid
  end

 end
spec/models/student_spec.rb

                                       ActiveRecord objects
 require File.dirname(__FILE__) + '/../spec_helper'

 describe Student do
                                       have a valid? method
  it quot;should never have a blank namequot; do
   no_name = Student.new( :name => “” )
   no_name.should_not be_valid
  end

 end
require File.dirname(__FILE__) + '/../spec_helper'

describe Student do

  it quot;should never have a blank namequot; do
   no_name = Student.new( :name => “” )
   no_name.should_not be_valid
  end

end




            Terminal: Running tests
require File.dirname(__FILE__) + '/../spec_helper'

describe Student do

  it quot;should never have a blank namequot; do
   no_name = Student.new( :name => “” )
   no_name.should_not be_valid
  end

end




            Terminal: Running tests
             $ ruby spec/models/student_spec.rb
             F

             Failed:
             Student should never have a blank name (FAILED)

             Finished in 0.1 seconds

             1 examples, 1 failures, 0 pending
app/models/student.rb
 class Student < ActiveRecord::Base

   has_many :beers

   validates_presence_of :name

 end
app/models/student.rb
 class Student < ActiveRecord::Base

   has_many :beers

   validates_presence_of :name

 end
Next 5 minutes
■   Add Rspec to your project
    ./script/generate rspec


■   Generate specs for your models - don’t replace files!
    ./script/generate rspec_model [model-name]


■   Clean spec files. Make sure they look like this.
      require File.dirname(__FILE__) + '/../spec_helper'

      describe Student do

      end



■   Build the test database
    rake db:migrate RAILS_ENV=test
Next 15 minutes
■   Spec out all your validations
■   First, all your specs should fail
■   Add the validations to your models
    validates_presence_of
    validates_uniqueness_of
    validates_format_of
    validates_length_of
    validates_numericality_of


■   Then, all your specs should pass
Connecting dots
.............
Connecting dots
Let’s make our view a little bit more fun
app/views/students/show.html.erb
<p>
  <b>Name:</b>
  <%=h @student.name %>
</p>


<%= link_to 'Edit', edit_person_path(@person) %> |
<%= link_to 'Back', people_path %>
app/views/students/show.html.erb
<p>
  <b>Name:</b>
  <%=h @student.name %>
</p>

<ul>
<% @student.beers.each do |beer| %>
  <li> 1 x <%= h beer.brand %> </li>
<% end %>
</ul>

<%= link_to 'Edit', edit_person_path(@person) %> |
<%= link_to 'Back', people_path %>
Next 10 minutes
■   Pimp one of your views!
You all get a PDF version of this book
to continue working on your project,
       thanks to pragprog.com




                            FREE!
</PRESENTATION>

More Related Content

What's hot

JavaScript - From Birth To Closure
JavaScript - From Birth To ClosureJavaScript - From Birth To Closure
JavaScript - From Birth To ClosureRobert Nyman
 
Ruby and rails - Advanced Training (Cybage)
Ruby and rails - Advanced Training (Cybage)Ruby and rails - Advanced Training (Cybage)
Ruby and rails - Advanced Training (Cybage)Gautam Rege
 
A Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented PhpA Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented PhpMichael Girouard
 
P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)lichtkind
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsMichael Pirnat
 
Class and Objects in PHP
Class and Objects in PHPClass and Objects in PHP
Class and Objects in PHPRamasubbu .P
 
Object Oriented PHP5
Object Oriented PHP5Object Oriented PHP5
Object Oriented PHP5Jason Austin
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.VimLin Yo-An
 
Introduction to Moose
Introduction to MooseIntroduction to Moose
Introduction to Moosethashaa
 
Ruby 入門 第一次就上手
Ruby 入門 第一次就上手Ruby 入門 第一次就上手
Ruby 入門 第一次就上手Wen-Tien Chang
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPWildan Maulana
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends旻琦 潘
 
Understanding Object Oriented Javascript - Coffee@DBG June
Understanding Object Oriented Javascript - Coffee@DBG JuneUnderstanding Object Oriented Javascript - Coffee@DBG June
Understanding Object Oriented Javascript - Coffee@DBG JuneDeepu S Nath
 
Moose - YAPC::NA 2012
Moose - YAPC::NA 2012Moose - YAPC::NA 2012
Moose - YAPC::NA 2012xSawyer
 
Beginning Object-Oriented JavaScript
Beginning Object-Oriented JavaScriptBeginning Object-Oriented JavaScript
Beginning Object-Oriented JavaScriptStoyan Stefanov
 
Web Security - Hands-on
Web Security - Hands-onWeb Security - Hands-on
Web Security - Hands-onAndrea Valenza
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonfRafael Dohms
 

What's hot (20)

JavaScript - From Birth To Closure
JavaScript - From Birth To ClosureJavaScript - From Birth To Closure
JavaScript - From Birth To Closure
 
Language supports it
Language supports itLanguage supports it
Language supports it
 
Ruby and rails - Advanced Training (Cybage)
Ruby and rails - Advanced Training (Cybage)Ruby and rails - Advanced Training (Cybage)
Ruby and rails - Advanced Training (Cybage)
 
SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
 
A Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented PhpA Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented Php
 
P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
Class and Objects in PHP
Class and Objects in PHPClass and Objects in PHP
Class and Objects in PHP
 
Object Oriented PHP5
Object Oriented PHP5Object Oriented PHP5
Object Oriented PHP5
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.Vim
 
Introduction to Moose
Introduction to MooseIntroduction to Moose
Introduction to Moose
 
Ruby 入門 第一次就上手
Ruby 入門 第一次就上手Ruby 入門 第一次就上手
Ruby 入門 第一次就上手
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOP
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
Understanding Object Oriented Javascript - Coffee@DBG June
Understanding Object Oriented Javascript - Coffee@DBG JuneUnderstanding Object Oriented Javascript - Coffee@DBG June
Understanding Object Oriented Javascript - Coffee@DBG June
 
Moose - YAPC::NA 2012
Moose - YAPC::NA 2012Moose - YAPC::NA 2012
Moose - YAPC::NA 2012
 
Beginning Object-Oriented JavaScript
Beginning Object-Oriented JavaScriptBeginning Object-Oriented JavaScript
Beginning Object-Oriented JavaScript
 
Web Security - Hands-on
Web Security - Hands-onWeb Security - Hands-on
Web Security - Hands-on
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
 
Ruby
RubyRuby
Ruby
 

Similar to Nedap Rails Workshop

Ruby 程式語言簡介
Ruby 程式語言簡介Ruby 程式語言簡介
Ruby 程式語言簡介Wen-Tien Chang
 
Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Benjamin Bock
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Brian Hogan
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsMatt Follett
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v RubyJano Suchal
 
Types End-to-End @ samsara
Types End-to-End @ samsaraTypes End-to-End @ samsara
Types End-to-End @ samsaraStephen Wan
 
Rapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and RailsRapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and Railselliando dias
 
Write your Ruby in Style
Write your Ruby in StyleWrite your Ruby in Style
Write your Ruby in StyleBhavin Javia
 
Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5Stephan Schmidt
 
Oto Brglez - Tips for better tests
Oto Brglez - Tips for better testsOto Brglez - Tips for better tests
Oto Brglez - Tips for better testsOto Brglez
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationAttila Balazs
 
Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Aslak Hellesøy
 
Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Aslak Hellesøy
 
Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Aslak Hellesøy
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1Jano Suchal
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Wen-Tien Chang
 
Rails 2010 Workshop
Rails 2010 WorkshopRails 2010 Workshop
Rails 2010 Workshopdtsadok
 

Similar to Nedap Rails Workshop (20)

Ruby 程式語言簡介
Ruby 程式語言簡介Ruby 程式語言簡介
Ruby 程式語言簡介
 
Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right Reasons
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
 
Types End-to-End @ samsara
Types End-to-End @ samsaraTypes End-to-End @ samsara
Types End-to-End @ samsara
 
Rapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and RailsRapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and Rails
 
Modern Perl
Modern PerlModern Perl
Modern Perl
 
Write your Ruby in Style
Write your Ruby in StyleWrite your Ruby in Style
Write your Ruby in Style
 
Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5
 
JavaScript Neednt Hurt - JavaBin talk
JavaScript Neednt Hurt - JavaBin talkJavaScript Neednt Hurt - JavaBin talk
JavaScript Neednt Hurt - JavaBin talk
 
10 classes
10 classes10 classes
10 classes
 
Oto Brglez - Tips for better tests
Oto Brglez - Tips for better testsOto Brglez - Tips for better tests
Oto Brglez - Tips for better tests
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl Presentation
 
Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009
 
Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009
 
Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009Ruby presentasjon på NTNU 22 april 2009
Ruby presentasjon på NTNU 22 april 2009
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽
 
Rails 2010 Workshop
Rails 2010 WorkshopRails 2010 Workshop
Rails 2010 Workshop
 

Recently uploaded

Dakshineswar Call Girls ✔ 8005736733 ✔ Hot Model With Sexy Bhabi Ready For Se...
Dakshineswar Call Girls ✔ 8005736733 ✔ Hot Model With Sexy Bhabi Ready For Se...Dakshineswar Call Girls ✔ 8005736733 ✔ Hot Model With Sexy Bhabi Ready For Se...
Dakshineswar Call Girls ✔ 8005736733 ✔ Hot Model With Sexy Bhabi Ready For Se...aamir
 
Beyond Bar & Club Udaipur CaLL GiRLS 09602870969
Beyond Bar & Club Udaipur CaLL GiRLS 09602870969Beyond Bar & Club Udaipur CaLL GiRLS 09602870969
Beyond Bar & Club Udaipur CaLL GiRLS 09602870969Apsara Of India
 
Low Rate Call Girls Ajmer Anika 8250192130 Independent Escort Service Ajmer
Low Rate Call Girls Ajmer Anika 8250192130 Independent Escort Service AjmerLow Rate Call Girls Ajmer Anika 8250192130 Independent Escort Service Ajmer
Low Rate Call Girls Ajmer Anika 8250192130 Independent Escort Service AjmerRiya Pathan
 
GV'S 24 CLUB & BAR CONTACT 09602870969 CALL GIRLS IN UDAIPUR ESCORT SERVICE
GV'S 24 CLUB & BAR CONTACT 09602870969 CALL GIRLS IN UDAIPUR ESCORT SERVICEGV'S 24 CLUB & BAR CONTACT 09602870969 CALL GIRLS IN UDAIPUR ESCORT SERVICE
GV'S 24 CLUB & BAR CONTACT 09602870969 CALL GIRLS IN UDAIPUR ESCORT SERVICEApsara Of India
 
Private Call Girls Durgapur - 8250192130 Escorts Service with Real Photos and...
Private Call Girls Durgapur - 8250192130 Escorts Service with Real Photos and...Private Call Girls Durgapur - 8250192130 Escorts Service with Real Photos and...
Private Call Girls Durgapur - 8250192130 Escorts Service with Real Photos and...Riya Pathan
 
Book Call Girls in Panchpota - 8250192130 | 24x7 Service Available Near Me
Book Call Girls in Panchpota - 8250192130 | 24x7 Service Available Near MeBook Call Girls in Panchpota - 8250192130 | 24x7 Service Available Near Me
Book Call Girls in Panchpota - 8250192130 | 24x7 Service Available Near Meanamikaraghav4
 
Call Girls Nashik Gayatri 7001305949 Independent Escort Service Nashik
Call Girls Nashik Gayatri 7001305949 Independent Escort Service NashikCall Girls Nashik Gayatri 7001305949 Independent Escort Service Nashik
Call Girls Nashik Gayatri 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
Independent Joka Escorts ✔ 8250192130 ✔ Full Night With Room Online Booking 2...
Independent Joka Escorts ✔ 8250192130 ✔ Full Night With Room Online Booking 2...Independent Joka Escorts ✔ 8250192130 ✔ Full Night With Room Online Booking 2...
Independent Joka Escorts ✔ 8250192130 ✔ Full Night With Room Online Booking 2...noor ahmed
 
Behala ( Call Girls ) Kolkata ✔ 6297143586 ✔ Hot Model With Sexy Bhabi Ready ...
Behala ( Call Girls ) Kolkata ✔ 6297143586 ✔ Hot Model With Sexy Bhabi Ready ...Behala ( Call Girls ) Kolkata ✔ 6297143586 ✔ Hot Model With Sexy Bhabi Ready ...
Behala ( Call Girls ) Kolkata ✔ 6297143586 ✔ Hot Model With Sexy Bhabi Ready ...ritikasharma
 
Low Rate Call Girls Gulbarga Anika 8250192130 Independent Escort Service Gulb...
Low Rate Call Girls Gulbarga Anika 8250192130 Independent Escort Service Gulb...Low Rate Call Girls Gulbarga Anika 8250192130 Independent Escort Service Gulb...
Low Rate Call Girls Gulbarga Anika 8250192130 Independent Escort Service Gulb...Riya Pathan
 
Top Rated Pune Call Girls Pimpri Chinchwad ⟟ 6297143586 ⟟ Call Me For Genuin...
Top Rated  Pune Call Girls Pimpri Chinchwad ⟟ 6297143586 ⟟ Call Me For Genuin...Top Rated  Pune Call Girls Pimpri Chinchwad ⟟ 6297143586 ⟟ Call Me For Genuin...
Top Rated Pune Call Girls Pimpri Chinchwad ⟟ 6297143586 ⟟ Call Me For Genuin...Call Girls in Nagpur High Profile
 
VIP Call Girls Asansol Ananya 8250192130 Independent Escort Service Asansol
VIP Call Girls Asansol Ananya 8250192130 Independent Escort Service AsansolVIP Call Girls Asansol Ananya 8250192130 Independent Escort Service Asansol
VIP Call Girls Asansol Ananya 8250192130 Independent Escort Service AsansolRiya Pathan
 
↑Top Model (Kolkata) Call Girls Behala ⟟ 8250192130 ⟟ High Class Call Girl In...
↑Top Model (Kolkata) Call Girls Behala ⟟ 8250192130 ⟟ High Class Call Girl In...↑Top Model (Kolkata) Call Girls Behala ⟟ 8250192130 ⟟ High Class Call Girl In...
↑Top Model (Kolkata) Call Girls Behala ⟟ 8250192130 ⟟ High Class Call Girl In...noor ahmed
 
👙 Kolkata Call Girls Shyam Bazar 💫💫7001035870 Model escorts Service
👙  Kolkata Call Girls Shyam Bazar 💫💫7001035870 Model escorts Service👙  Kolkata Call Girls Shyam Bazar 💫💫7001035870 Model escorts Service
👙 Kolkata Call Girls Shyam Bazar 💫💫7001035870 Model escorts Serviceanamikaraghav4
 
Jinx Manga-Season 1 - Chapters Summary.docx
Jinx Manga-Season 1 - Chapters Summary.docxJinx Manga-Season 1 - Chapters Summary.docx
Jinx Manga-Season 1 - Chapters Summary.docxJinx Manga
 
VIP Call Girls Sonagachi - 8250192130 Escorts Service 50% Off with Cash ON De...
VIP Call Girls Sonagachi - 8250192130 Escorts Service 50% Off with Cash ON De...VIP Call Girls Sonagachi - 8250192130 Escorts Service 50% Off with Cash ON De...
VIP Call Girls Sonagachi - 8250192130 Escorts Service 50% Off with Cash ON De...anamikaraghav4
 
VIP Call Girls Service Banjara Hills Hyderabad Call +91-8250192130
VIP Call Girls Service Banjara Hills Hyderabad Call +91-8250192130VIP Call Girls Service Banjara Hills Hyderabad Call +91-8250192130
VIP Call Girls Service Banjara Hills Hyderabad Call +91-8250192130Suhani Kapoor
 
Call Girls Manjri Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Manjri Call Me 7737669865 Budget Friendly No Advance BookingCall Girls Manjri Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Manjri Call Me 7737669865 Budget Friendly No Advance Bookingroncy bisnoi
 

Recently uploaded (20)

Dakshineswar Call Girls ✔ 8005736733 ✔ Hot Model With Sexy Bhabi Ready For Se...
Dakshineswar Call Girls ✔ 8005736733 ✔ Hot Model With Sexy Bhabi Ready For Se...Dakshineswar Call Girls ✔ 8005736733 ✔ Hot Model With Sexy Bhabi Ready For Se...
Dakshineswar Call Girls ✔ 8005736733 ✔ Hot Model With Sexy Bhabi Ready For Se...
 
Beyond Bar & Club Udaipur CaLL GiRLS 09602870969
Beyond Bar & Club Udaipur CaLL GiRLS 09602870969Beyond Bar & Club Udaipur CaLL GiRLS 09602870969
Beyond Bar & Club Udaipur CaLL GiRLS 09602870969
 
Low Rate Call Girls Ajmer Anika 8250192130 Independent Escort Service Ajmer
Low Rate Call Girls Ajmer Anika 8250192130 Independent Escort Service AjmerLow Rate Call Girls Ajmer Anika 8250192130 Independent Escort Service Ajmer
Low Rate Call Girls Ajmer Anika 8250192130 Independent Escort Service Ajmer
 
GV'S 24 CLUB & BAR CONTACT 09602870969 CALL GIRLS IN UDAIPUR ESCORT SERVICE
GV'S 24 CLUB & BAR CONTACT 09602870969 CALL GIRLS IN UDAIPUR ESCORT SERVICEGV'S 24 CLUB & BAR CONTACT 09602870969 CALL GIRLS IN UDAIPUR ESCORT SERVICE
GV'S 24 CLUB & BAR CONTACT 09602870969 CALL GIRLS IN UDAIPUR ESCORT SERVICE
 
Private Call Girls Durgapur - 8250192130 Escorts Service with Real Photos and...
Private Call Girls Durgapur - 8250192130 Escorts Service with Real Photos and...Private Call Girls Durgapur - 8250192130 Escorts Service with Real Photos and...
Private Call Girls Durgapur - 8250192130 Escorts Service with Real Photos and...
 
Book Call Girls in Panchpota - 8250192130 | 24x7 Service Available Near Me
Book Call Girls in Panchpota - 8250192130 | 24x7 Service Available Near MeBook Call Girls in Panchpota - 8250192130 | 24x7 Service Available Near Me
Book Call Girls in Panchpota - 8250192130 | 24x7 Service Available Near Me
 
Call Girls Nashik Gayatri 7001305949 Independent Escort Service Nashik
Call Girls Nashik Gayatri 7001305949 Independent Escort Service NashikCall Girls Nashik Gayatri 7001305949 Independent Escort Service Nashik
Call Girls Nashik Gayatri 7001305949 Independent Escort Service Nashik
 
Call Girls South Avenue Delhi WhatsApp Number 9711199171
Call Girls South Avenue Delhi WhatsApp Number 9711199171Call Girls South Avenue Delhi WhatsApp Number 9711199171
Call Girls South Avenue Delhi WhatsApp Number 9711199171
 
Independent Joka Escorts ✔ 8250192130 ✔ Full Night With Room Online Booking 2...
Independent Joka Escorts ✔ 8250192130 ✔ Full Night With Room Online Booking 2...Independent Joka Escorts ✔ 8250192130 ✔ Full Night With Room Online Booking 2...
Independent Joka Escorts ✔ 8250192130 ✔ Full Night With Room Online Booking 2...
 
Behala ( Call Girls ) Kolkata ✔ 6297143586 ✔ Hot Model With Sexy Bhabi Ready ...
Behala ( Call Girls ) Kolkata ✔ 6297143586 ✔ Hot Model With Sexy Bhabi Ready ...Behala ( Call Girls ) Kolkata ✔ 6297143586 ✔ Hot Model With Sexy Bhabi Ready ...
Behala ( Call Girls ) Kolkata ✔ 6297143586 ✔ Hot Model With Sexy Bhabi Ready ...
 
Low Rate Call Girls Gulbarga Anika 8250192130 Independent Escort Service Gulb...
Low Rate Call Girls Gulbarga Anika 8250192130 Independent Escort Service Gulb...Low Rate Call Girls Gulbarga Anika 8250192130 Independent Escort Service Gulb...
Low Rate Call Girls Gulbarga Anika 8250192130 Independent Escort Service Gulb...
 
Top Rated Pune Call Girls Pimpri Chinchwad ⟟ 6297143586 ⟟ Call Me For Genuin...
Top Rated  Pune Call Girls Pimpri Chinchwad ⟟ 6297143586 ⟟ Call Me For Genuin...Top Rated  Pune Call Girls Pimpri Chinchwad ⟟ 6297143586 ⟟ Call Me For Genuin...
Top Rated Pune Call Girls Pimpri Chinchwad ⟟ 6297143586 ⟟ Call Me For Genuin...
 
VIP Call Girls Asansol Ananya 8250192130 Independent Escort Service Asansol
VIP Call Girls Asansol Ananya 8250192130 Independent Escort Service AsansolVIP Call Girls Asansol Ananya 8250192130 Independent Escort Service Asansol
VIP Call Girls Asansol Ananya 8250192130 Independent Escort Service Asansol
 
↑Top Model (Kolkata) Call Girls Behala ⟟ 8250192130 ⟟ High Class Call Girl In...
↑Top Model (Kolkata) Call Girls Behala ⟟ 8250192130 ⟟ High Class Call Girl In...↑Top Model (Kolkata) Call Girls Behala ⟟ 8250192130 ⟟ High Class Call Girl In...
↑Top Model (Kolkata) Call Girls Behala ⟟ 8250192130 ⟟ High Class Call Girl In...
 
👙 Kolkata Call Girls Shyam Bazar 💫💫7001035870 Model escorts Service
👙  Kolkata Call Girls Shyam Bazar 💫💫7001035870 Model escorts Service👙  Kolkata Call Girls Shyam Bazar 💫💫7001035870 Model escorts Service
👙 Kolkata Call Girls Shyam Bazar 💫💫7001035870 Model escorts Service
 
Jinx Manga-Season 1 - Chapters Summary.docx
Jinx Manga-Season 1 - Chapters Summary.docxJinx Manga-Season 1 - Chapters Summary.docx
Jinx Manga-Season 1 - Chapters Summary.docx
 
VIP Call Girls Sonagachi - 8250192130 Escorts Service 50% Off with Cash ON De...
VIP Call Girls Sonagachi - 8250192130 Escorts Service 50% Off with Cash ON De...VIP Call Girls Sonagachi - 8250192130 Escorts Service 50% Off with Cash ON De...
VIP Call Girls Sonagachi - 8250192130 Escorts Service 50% Off with Cash ON De...
 
VIP Call Girls Service Banjara Hills Hyderabad Call +91-8250192130
VIP Call Girls Service Banjara Hills Hyderabad Call +91-8250192130VIP Call Girls Service Banjara Hills Hyderabad Call +91-8250192130
VIP Call Girls Service Banjara Hills Hyderabad Call +91-8250192130
 
Call Girls Manjri Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Manjri Call Me 7737669865 Budget Friendly No Advance BookingCall Girls Manjri Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Manjri Call Me 7737669865 Budget Friendly No Advance Booking
 
Call Girls Chirag Delhi Delhi WhatsApp Number 9711199171
Call Girls Chirag Delhi Delhi WhatsApp Number 9711199171Call Girls Chirag Delhi Delhi WhatsApp Number 9711199171
Call Girls Chirag Delhi Delhi WhatsApp Number 9711199171
 

Nedap Rails Workshop

  • 2. Hellow Bart André Dirkjan
  • 3. Hellow Bart André Dirkjan
  • 4.
  • 6. Development is more than coding
  • 7.
  • 8.
  • 9.
  • 12. Language Ruby on Rails
  • 13. Language Ruby on Rails Framework
  • 14. What are we doing today? 1 Ruby basics 2 Rails terminology / vision 3 Build something simple
  • 15. What are we doing today? 1 Ruby basics st .... ut fir B 2 Rails terminology / vision 3 Build something simple
  • 17. Address Book ■ Generate a new Rails Application ■ Generate some stuff ■ Prepare the database ■ Start the application ■ View application and be excited!
  • 18.
  • 19.
  • 21. Terminal $ rails address_book create create app/controllers create app/helpers create app/models create app/views/layouts create test/functional create test/integration ... create log/server.log create log/production.log create log/development.log create log/test.log
  • 22. Terminal $ rails address_book create create app/controllers create app/helpers create app/models create app/views/layouts create test/functional create test/integration ... create log/server.log create log/production.log create log/development.log create log/test.log $ cd address_book
  • 24. Terminal $ ./script/generate scaffold person name:string exists app/controllers/ exists app/helpers/ create app/views/people ...
  • 25. ./script/destroy to undo Terminal $ ./script/generate scaffold person name:string exists app/controllers/ exists app/helpers/ create app/views/people ...
  • 27. Terminal $ rake db:migrate == 00000000000000 CreatePeople: migrating ============= -- create_table(:people) -> 0.0177s == 00000000000000 CreatePeople: migrated (0.0180s) ====
  • 28. rake db:rollback to undo Terminal $ rake db:migrate == 00000000000000 CreatePeople: migrating ============= -- create_table(:people) -> 0.0177s == 00000000000000 CreatePeople: migrated (0.0180s) ====
  • 29. ⌘N
  • 31. Terminal $ cd address_book
  • 32. Terminal $ cd address_book $ ./script/server => Booting Mongrel => Rails 2.1.0 application starting on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server ** Starting Mongrel listening at 0.0.0.0:3000 ** Starting Rails with development environment... ** Rails loaded. ** Loading any Rails specific GemPlugins ** Signals ready. TERM => stop. USR2 => restart. ** Rails signals registered. ** Mongrel 1.1.4 available at 0.0.0.0:3000 ** Use CTRL-C to stop.
  • 33.
  • 35.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42. It all seems like magic...
  • 44. This is normal. It will pass.
  • 46. Ruby
  • 47. The basics ■ Objects ■ Variables ■ Methods ■ Inheritance & Modules ■ Blocks
  • 49. Objects, variables & methods class Person attr_accessor :name def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end
  • 50. class name Objects, variables & methods class Person attr_accessor :name def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end
  • 51. class name Objects, variables & methods instance variable class Person attr_accessor :name def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end
  • 52. class name Objects, variables & methods instance variable class Person method attr_accessor :name def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end
  • 53. class Person attr_accessor :name def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end Console: using a class
  • 54. class Person attr_accessor :name def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end Console: using a class >> andre = Person.new >> andre.name = ‘Andre’
  • 55. class Person attr_accessor :name def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end Console: using a class >> andre = Person.new >> andre.name = ‘Andre’ >> bart = Person.new >> bart.name = ‘Bart’
  • 56. class Person attr_accessor :name def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end Console: using a class >> andre = Person.new >> andre.name = ‘Andre’ >> bart = Person.new >> bart.name = ‘Bart’ >> bart.insults(andre, “dog”) “Bart thinks Andre is a stupid dog!”
  • 57. Inheritance class Person attr_accessor :name end class Student < Person def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end
  • 58. Inheritance Student inherits class Person attr_accessor :name from person end class Student < Person def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end
  • 61. Driving skill Person Woman Man
  • 62. Driving skill Person Woman Man
  • 63. Person Driving skill Woman Man
  • 64. Person Woman Man Driving skill Andre Bart
  • 65. Modules module Insulting def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end class Person attr_accessor :name include Insulting end
  • 66. Creates an Modules ‘Insulting’ module module Insulting def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end class Person attr_accessor :name include Insulting end
  • 67. Creates an Modules ‘Insulting’ module module Insulting def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end Person end classes can class Person ‘Insult’ attr_accessor :name include Insulting end
  • 68. Creates an Modules ‘Insulting’ module module Insulting def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end Person end classes can class Person class Robot ‘Insult’ attr_accessor :name attr_accessor :name include Insulting include Insulting end end Everyone can insult now!
  • 69. module Insulting def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end class Person attr_accessor :name end Console: extending on the fly
  • 70. module Insulting def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end class Person attr_accessor :name end Console: extending on the fly >> andre = Person.new >> andre.name = “Andre” >> andre.extend(Insulting) nil
  • 71. module Insulting def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end class Person attr_accessor :name end Console: extending on the fly >> andre = Person.new >> andre.name = “Andre” >> andre.extend(Insulting) nil >> andre.insults(bart) “Andre thinks Bart is a stupid cow!”
  • 72. module Insulting def insults(other, object=quot;cowquot;) quot;#{name} thinks #{other.name} is a stupid #{object}!quot; end end class Person attr_accessor :name end Console: extending on the flyWe could also extend an entire class like this! >> andre = Person.new >> andre.name = “Andre” >> andre.extend(Insulting) nil >> andre.insults(bart) “Andre thinks Bart is a stupid cow!”
  • 73. Man Person Driving skill Insulting Gardening
  • 74. Man Person Driving skill Insulting Gardening How do we test if this man can insult?
  • 76. If it walks like a duck and quacks like a duck, it's a duck. — Lisa Graves
  • 79. Person Woman Man Driver
  • 80. Person Driving skill Woman Man
  • 82. class Person attr_accessor :name end Console: using blocks
  • 83. class Person attr_accessor :name end Console: using blocks >> people [<#Person:0x00 @name=”Andre”>,<#Person:0x00 @name=”Bart”>]
  • 84. class Person attr_accessor :name end Console: using blocks >> people [<#Person:0x00 @name=”Andre”>,<#Person:0x00 @name=”Bart”>] >> people.map{ |item| “#{item.name} is kewl” } [“Andre is kewl”, “Bart is kewl”]
  • 85. class Person attr_accessor :name end Console: using blocks also have: select, reject and inject to We work with collections! >> people [<#Person:0x00 @name=”Andre”>,<#Person:0x00 @name=”Bart”>] >> people.map{ |item| “#{item.name} is kewl” } [“Andre is kewl”, “Bart is kewl”]
  • 87. You know Ruby! Sorta...
  • 88. You know Ruby! Sorta...
  • 92. VIEW MVC MODEL CONTROLLER
  • 93. Models Talk to the database, contain business logic Controllers Provide the glue, prepare data when needed Views Show the content to the user
  • 94. You are not a beautiful and unique snowflake. You are the same decaying organic matter as everyone else, and we are all a part of the same compost pile. — Tyler Durden, Fight Club
  • 95. SEE CHANGE RESOURCE ADD REMOVE
  • 96. Show me something SEE CHANGE RESOURCE ADD REMOVE
  • 97. Show me something SEE CHANGE RESOURCE Add someone ADD REMOVE
  • 98. Show me something SEE CHANGE Change something RESOURCE Add someone ADD REMOVE
  • 99. Show me something SEE CHANGE Change something RESOURCE Add someone Delete stuff ADD REMOVE
  • 100. CREATE UPDATE CRUD READ DELETE
  • 101. CREATE UPDATE CRUD READ DELETE
  • 102. CREATE UPDATE CRUD READ DELETE HTTP !
  • 103. POST CREATE UPDATE CRUD READ DELETE HTTP !
  • 104. POST CREATE UPDATE CRUD READ GET DELETE HTTP !
  • 105. POST PUT CREATE UPDATE CRUD READ GET DELETE HTTP !
  • 106. POST PUT CREATE UPDATE CRUD READ GET DELETE DELETE HTTP !
  • 108. UNIVERSAL URI IDE NT IFI ER RESOURCE
  • 109.
  • 110. ADD POST /people
  • 111. ADD POST /people SEE GET /people
  • 112. ADD POST /people SEE GET /people CHANGE PUT /people/1
  • 113. ADD POST /people SEE GET /people CHANGE PUT /people/1 REMOVE DELETE /people/1
  • 114. REPRESENTATIONAL STATE TRANSFER REST
  • 116. RAILS CONTROLLER ACTIONS INDEX NEW EDIT SHOW CREATE UPDATE DESTROY
  • 120. 2 hrs IT WON’T BE ENOUGH...
  • 121.
  • 122. First 15 minutes ■ You should have an idea ■ You should have a rough sketch ■ You should have thought of what models you need ■ You should think of their relation to each other ■ Pick an pair of models with a 1..* relationship 1 Student * Beer
  • 123. Next 10 minutes ■ You should have a new rails app $ rails [your_app_name] ■ You should have generated the models $ ./script/generate scaffold [model_name] [attr]:[type type = string, text, integer, float, boolean, date, time, datetime reserved attrs => type, version
  • 124. mate .
  • 125.
  • 126.
  • 127.
  • 128. App structure - app - models - views - controllers - config - db - migrate
  • 129. App structure - app - models the model files - views - controllers - config - db - migrate
  • 130. App structure - app - models the model files - views templates for HTML - controllers - config - db - migrate
  • 131. App structure - app - models the model files - views templates for HTML - controllers the controller files - config - db - migrate
  • 132. App structure - app - models the model files - views templates for HTML - controllers the controller files - config basic configuration - db - migrate
  • 133. App structure - app - models the model files - views templates for HTML - controllers the controller files - config basic configuration - db - migrate database migrations
  • 135. db/migrate/00000000_create_people.rb class CreatePeople < ActiveRecord::Migration def self.up create_table :people do |t| t.string :name t.timestamps end end def self.down drop_table :people end end
  • 136. Create a ‘People’ db/migrate/00000000_create_people.rb table on UP class CreatePeople < ActiveRecord::Migration def self.up create_table :people do |t| t.string :name t.timestamps end end def self.down drop_table :people end end
  • 137. Create a ‘People’ db/migrate/00000000_create_people.rb With a ‘Name’ table on UP String class CreatePeople < ActiveRecord::Migration def self.up create_table :people do |t| t.string :name t.timestamps end end def self.down drop_table :people end end
  • 138. Create a ‘People’ db/migrate/00000000_create_people.rb With a ‘Name’ table on UP String class CreatePeople < ActiveRecord::Migration def self.up create_table :people do |t| t.string :name t.timestamps end end def self.down drop_table :people And some time-stamps: end end created_at & updated_at
  • 139. Create a ‘People’ db/migrate/00000000_create_people.rb With a ‘Name’ table on UP String class CreatePeople < ActiveRecord::Migration def self.up create_table :people do |t| t.string :name t.timestamps end end def self.down drop_table :people And some time-stamps: end end created_at & updated_at Drop the table on DOWN
  • 141. 1 Student * Beer app/models/student.rb class Student < ActiveRecord::Base has_many :beers end app/models/beer.rb class Beer < ActiveRecord::Base belongs_to :student end
  • 142. db/migrate/00000000_create_beers.rb class CreateBeers < ActiveRecord::Migration def self.up create_table :beers do |t| t.string :brand t.references :student t.timestamps end end def self.down drop_table :beers end end
  • 143. db/migrate/00000000_create_beers.rb Add a reference to Student (:student_id) class CreateBeers < ActiveRecord::Migration def self.up create_table :beers do |t| t.string :brand t.references :student t.timestamps end end def self.down drop_table :beers end end
  • 144. Next 10 minutes ■ You should update your model files when needed belongs_to, has_many, has_one, has_many :through ■ You should add references to migrations t.references :student
  • 145. Next 5 minutes ■ You should have migrated the database $ rake db:migrate ■ You should have a running server $ ./script/server ■ You should see your app $ open http://localhost:3000
  • 146. Routes
  • 147. config/routes.rb ActionController::Routing::Routes.draw do |map| map.resources :students map.resources :beers # You can have the root of your site routed with map.root # map.root :controller => quot;welcomequot; map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end
  • 148. config/routes.rb Routes for each resource ActionController::Routing::Routes.draw do |map| map.resources :students map.resources :beers # You can have the root of your site routed with map.root # map.root :controller => quot;welcomequot; map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end
  • 149. config/routes.rb Routes for each resource ActionController::Routing::Routes.draw do |map| map.resources :students map.resources :beers # You can have the root of your site routed with map.root # map.root :controller => quot;welcomequot; map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end Remove # and change :controller to ‘students’
  • 150. ADD POST /people SEE GET /people CHANGE PUT /people/1 REMOVE DELETE /people/1 SEE GET /people/1 CHANGE GET /people/1/edit ADD GET /people/new
  • 151. Next 5 minutes ■ Change the routes Uncomment & choose default controller ■ Remove ‘public/index.html’ $ rm public/index.html ■ Refresh your browser
  • 153. One class per table One instance per row
  • 154. One class per utable b tes at tri sare lumn Co One instance per row
  • 157. andre = Student.new( :name => “Andre” ) andre.save
  • 158. Next 10 minutes ■ You should play with your app, create some instances We created a student named “Andre” ■ You should start a console $ ./script/console ■ You should build a few relationships using the console >> andre = Student.find_by_name(“Andre”) >> beer = andre.beers.create( :brand => “Grolsch” ) >> beer.student.name ”Andre”
  • 159. Views
  • 160. app/views/beer/new.html.erb <h1>New beer</h1> <% form_for(@beer) do |f| %> <%= f.error_messages %> <p> <%= f.label :brand %><br /> <%= f.text_field :brand %> </p> <p> <%= f.submit quot;Createquot; %> </p> <% end %> <%= link_to 'Back', beers_path %>
  • 161. Title of the page app/views/beer/new.html.erb <h1>New beer</h1> <% form_for(@beer) do |f| %> <%= f.error_messages %> <p> <%= f.label :brand %><br /> <%= f.text_field :brand %> </p> <p> <%= f.submit quot;Createquot; %> </p> <% end %> <%= link_to 'Back', beers_path %>
  • 162. Title of the page app/views/beer/new.html.erb A form <h1>New beer</h1> <% form_for(@beer) do |f| %> <%= f.error_messages %> <p> <%= f.label :brand %><br /> <%= f.text_field :brand %> </p> <p> <%= f.submit quot;Createquot; %> </p> <% end %> <%= link_to 'Back', beers_path %>
  • 163. Title of the page app/views/beer/new.html.erb A form <h1>New beer</h1> <% form_for(@beer) do |f| %> <%= f.error_messages %> <p> <%= f.label :brand %><br /> <%= f.text_field :brand %> Show errors messages if </p> <p> something goes wrong <%= f.submit quot;Createquot; %> </p> <% end %> <%= link_to 'Back', beers_path %>
  • 164. Title of the page app/views/beer/new.html.erb A form <h1>New beer</h1> <% form_for(@beer) do |f| %> <%= f.error_messages %> <p> <%= f.label :brand %><br /> <%= f.text_field :brand %> Show errors messages if </p> <p> something goes wrong <%= f.submit quot;Createquot; %> Some fields </p> <% end %> and a button <%= link_to 'Back', beers_path %>
  • 165. Title of the page app/views/beer/new.html.erb A form <h1>New beer</h1> <% form_for(@beer) do |f| %> <%= f.error_messages %> <p> <%= f.label :brand %><br /> <%= f.text_field :brand %> Show errors messages if </p> <p> something goes wrong <%= f.submit quot;Createquot; %> Some fields </p> <% end %> and a button <%= link_to 'Back', beers_path %> Back link
  • 166. app/views/beer/new.html.erb <h1>New beer</h1> <% form_for(@beer) do |f| %> <%= f.error_messages %> <p> <%= f.label :brand %><br /> <%= f.text_field :brand %> </p> <p> <%= f.submit quot;Createquot; %> </p> <% end %> <%= link_to 'Back', beers_path %>
  • 167. app/views/beer/new.html.erb <h1>New beer</h1> <% form_for(@beer) do |f| %> <%= f.error_messages %> <p> <%= f.label :brand %><br /> <%= f.text_field :brand %> </p> <p> <%= f.label :student %><br /> <%= f.collection_select :student_id, Student.find(:all), :id, :name %> </p> <p> <%= f.submit quot;Createquot; %> </p> <% end %> <%= link_to 'Back', beers_path %>
  • 168. Next 15 minutes ■ Should be able to set a belongs_to relationship collection_select ■ Relationship must be able to be set on new and existing objects Change both the edit and new view! ■ Test that it really works! Try to edit the show view to represent the object relationship so another human understands it!
  • 169. Validations This is a behaviour...
  • 170. Validations This is a behaviour...
  • 171. BDD BEHAVIOUR DRIVEN DEVELOPMENT
  • 172. How should a student behave?
  • 173. Student ■ should never have a blank name
  • 175. Terminal $ ./script/generate rspec create lib/tasks/rspec.rake create script/autospec create script/spec create script/spec_server create spec create spec/rcov.opts create spec/spec.opts create spec/spec_helper.rb create stories create stories/all.rb create stories/helper.rb
  • 176. Terminal $ ./script/generate rspec create lib/tasks/rspec.rake create script/autospec create script/spec create script/spec_server create spec create spec/rcov.opts create spec/spec.opts create spec/spec_helper.rb create stories create stories/all.rb create stories/helper.rb $ ./script/generate rspec_model student
  • 177. Terminal $ ./script/generate rspec create lib/tasks/rspec.rake create script/autospec create script/spec create script/spec_server create spec create spec/rcov.opts create spec/spec.opts create spec/spec_helper.rb create stories create stories/all.rb create stories/helper.rb $ ./script/generate rspec_model student $ rake db:migrate RAILS_ENV=test
  • 178. spec/models/student_spec.rb require File.dirname(__FILE__) + '/../spec_helper' describe Student do it quot;should never have a blank namequot; do no_name = Student.new( :name => “” ) no_name.should_not be_valid end end
  • 179. spec/models/student_spec.rb ActiveRecord objects require File.dirname(__FILE__) + '/../spec_helper' describe Student do have a valid? method it quot;should never have a blank namequot; do no_name = Student.new( :name => “” ) no_name.should_not be_valid end end
  • 180. require File.dirname(__FILE__) + '/../spec_helper' describe Student do it quot;should never have a blank namequot; do no_name = Student.new( :name => “” ) no_name.should_not be_valid end end Terminal: Running tests
  • 181. require File.dirname(__FILE__) + '/../spec_helper' describe Student do it quot;should never have a blank namequot; do no_name = Student.new( :name => “” ) no_name.should_not be_valid end end Terminal: Running tests $ ruby spec/models/student_spec.rb F Failed: Student should never have a blank name (FAILED) Finished in 0.1 seconds 1 examples, 1 failures, 0 pending
  • 182. app/models/student.rb class Student < ActiveRecord::Base has_many :beers validates_presence_of :name end
  • 183. app/models/student.rb class Student < ActiveRecord::Base has_many :beers validates_presence_of :name end
  • 184. Next 5 minutes ■ Add Rspec to your project ./script/generate rspec ■ Generate specs for your models - don’t replace files! ./script/generate rspec_model [model-name] ■ Clean spec files. Make sure they look like this. require File.dirname(__FILE__) + '/../spec_helper' describe Student do end ■ Build the test database rake db:migrate RAILS_ENV=test
  • 185. Next 15 minutes ■ Spec out all your validations ■ First, all your specs should fail ■ Add the validations to your models validates_presence_of validates_uniqueness_of validates_format_of validates_length_of validates_numericality_of ■ Then, all your specs should pass
  • 188. Let’s make our view a little bit more fun
  • 189. app/views/students/show.html.erb <p> <b>Name:</b> <%=h @student.name %> </p> <%= link_to 'Edit', edit_person_path(@person) %> | <%= link_to 'Back', people_path %>
  • 190. app/views/students/show.html.erb <p> <b>Name:</b> <%=h @student.name %> </p> <ul> <% @student.beers.each do |beer| %> <li> 1 x <%= h beer.brand %> </li> <% end %> </ul> <%= link_to 'Edit', edit_person_path(@person) %> | <%= link_to 'Back', people_path %>
  • 191. Next 10 minutes ■ Pimp one of your views!
  • 192. You all get a PDF version of this book to continue working on your project, thanks to pragprog.com FREE!