• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Nedap Rails Workshop
 

Nedap Rails Workshop

on

  • 2,633 views

 

Statistics

Views

Total Views
2,633
Views on SlideShare
2,459
Embed Views
174

Actions

Likes
3
Downloads
45
Comments
0

5 Embeds 174

http://www.movesonrails.com 133
http://movesonrails.com 32
http://www.linkedin.com 6
http://64.233.163.132 2
http://74.125.77.132 1

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Nedap Rails Workshop Nedap Rails Workshop Presentation Transcript

    • 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>