@speaker  = { :name   =>  ‘Matt Yoho’ , :company  =>  EdgeCase , :writes   => [ ‘Ruby on Rails’ ], :loves   => [ ‘Comic Bo...
Goals
Rails is a Domain Specific Language for web applications written in and on top of Ruby.
Rails 1.0 December 2005
Rails 2.0 December 2007
Rails 2.3 March 2009
Rails  3 .0 August 2010
Rails  3 .0.3 November 2010
Agenda
1) Rails Overview
2) Highlight new features
3) Example app
Rails concepts
MVC
M odel VC
MV iew C
MV C ontroller
Models Views Controllers Model  View Controller
Models Views Controllers Helpers Model  View Controller
Models Views Controllers Routes Helpers Model  View Controller
class   Movie  <  ActiveRecord :: Base has_many  :nights belongs_to  :genre validates  :title , :presence   =>  true valid...
Model Domain logic, data persistence. Implement ActiveModel in Rails 3 class   Movie  <  ActiveRecord :: Base has_many  :n...
Model Associations Validations Lifecycle callbacks class   Movie  <  ActiveRecord :: Base has_many  :nights belongs_to  :g...
< div  class= ”movie” > < img src= ” <%=  @movie .poster_url %> ” alt= ” <%=  @movie .title %> ”  /> < h3 ><%=  @movie .ti...
View Nested structure. Layouts Templates Partials Partials
View Contain < head > and < body > tags, basic stylesheets and JavaScript links. One or a few per app. Layouts
View Templates Contain page-specific markup and exist for approximately each controller action.
View Small, reusable template components. Partials Partials
class   MoviesController  < ApplicationController before_filter  :user_of_age? def  show id  = params[ :id ] @movie  =  Mo...
Controller Rendering Redirection Filters class   MoviesController  < ApplicationController before_filter  :user_of_age? de...
module   MoviesHelper def  movie_name(night)  if  night.movie.present? night.movie_title else &quot;DUNNO YET&quot; end   ...
Movies :: Application .routes.draw  do resources  :movies   do   resources  :votes ,  :only  => [ :create , :destroy ]  en...
class   Notifier  < ActionMailer :: Base   default  :from  => &quot;invites@movienight.com&quot; ,  :subject  =>  &quot;Yo...
DRY
Don’t Repeat Yourself
class   CreateMovies  <  ActiveRecord :: Migration def self .up create_table   :movies   do   | t | t.string   :title t.st...
class   Movie  <  ActiveRecord :: Base validates   :title , :presence   =>  true validates   :imdb_id , :presence   =>  tr...
ConventionConfiguration
REST
Define APIs
Define RESTful APIs
Resources
Identified by URIs
http://movienight.com/movies/123
Movie id = 123 ... http://movienight.com/movies/123
May be nested
http://movienight.com/movies/123/actors/4
Movie id = 123 http://movienight.com/movies/123/actors/4 Actor id = 4
May have multiple representations
http://movienight.com/movies/123.json
http://movienight.com/movies/123.json {&quot;movie&quot; : {&quot;alt_title&quot; : &quot;Batman Begins&quot;, &quot;creat...
http://movienight.com/movies/123.xml
http://movienight.com/movies/123.xml <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> <movie> <title>Batman Begi...
Rely on HTTP content type negotiation
HTTP headers
HTTP headers http://movienight.com/movies/123.json
Accept:  application/json, text/javascript, */* ; Request header
Content-Type: application/json; Response header
CRUD via HTTP VERBS
GET POST PUT DELETE HTTP verbs
READ CREATE UPDATE DELETE CRUD operations
SHOW CREATE UPDATE DESTROY Rails controller actions
SHOW CREATE UPDATE DESTROY NEW EDIT INDEX
GET /movies/123 HTTP/1.1 Accept:text/html
GET /movies/123 HTTP/1.1 Accept:text/html CRUD op
GET /movies/123 HTTP/1.1 Accept:text/html Resource
GET /movies/123 HTTP/1.1 Accept:text/html MoviesController#show
Strongly encouraged by Rails
Request -> Response Cycle
Models Views Controllers Routes Request-response cycle Client
Models Views Controllers Routes Request-response cycle Client
Models Views Controllers Routes Request-response cycle Client
Models Views Controllers Routes Request-response cycle Client
Models Views Controllers Routes Request-response cycle Client
Models Views Controllers Routes Request-response cycle Client
Models Views Controllers Routes Request-response cycle Client
Models Views Controllers Routes Request-response cycle Client
Models Views Controllers Routes Request-response cycle Client Webpage!
Feature details
 
 
Bundler
Commands
rails new ~/app/name
rails new ~/app/name -T -J
rails new ~/app/name -T -J -T = Skip Test::Unit
rails new ~/app/name -T -J -J = Skip Prototype
rails generate < thing >
rails server
rails console
Dependency Management
can't activate cucumber (= 0.4.4, runtime) for [], already activated cucumber-0.6.1 for [] (Gem::LoadError)
$ gem install rails -v2.3.10Successfully installed activesupport-2.3.9Successfully installed activerecord-2.3.9Successfull...
$ gem install rails -v3.0.3Successfully installed activesupport-3.0.3Successfully installed builder-2.1.2Successfully inst...
$ gem install rails -v3.0.3Successfully installed activesupport-3.0.3Successfully installed builder-2.1.2Successfully inst...
Gemfile
source  'http://rubygems.org' gem  'rails' ,  '~> 3.0.3' gem  'basic_assumption' ,  '~> 0.4.1' gem  'devise' ,  '~> 1.1.5'...
source  'http://rubygems.org'
gem  'rails' ,  '~> 3.0.3'
gem  'rails' ,  '~> 3.0.3' Name
gem  'rails' ,  '~> 3.0.3' Version
:mri :mri_18 :mri_19 :mswin :jruby Platforms
gem  'ruby-debug' , :platforms   =>   :mri_18
gem  'ruby-debug19' , :platforms   =>   :mri_19
Install from Git
gem  'basic_assumption' , :git   =>  'git://github.com/mattyoho/basic_assumption.git' , :branch  =>  'experimental'
gem  'basic_assumption' , :git   =>  'git://github.com/mattyoho/basic_assumption.git' , :branch  =>  'experimental' GitHub...
gem  'basic_assumption' , :git   =>  'git://github.com/mattyoho/basic_assumption.git' , :branch  =>  'experimental' Git re...
bundle install
group  :test   do   gem  'rspec-rails'   gem  'cucumber'   gem  'fakeweb' end end
bundle install --without test
bundle open < gem name >
bundle open < gem name >
bundle update
bundle package
http://gembundler.org/ http://gembundler.com/man/gemfile.5.html
MATT YOHO RAILS 3 FROM A TO Z Models MATT YOHO RAILS 3 FROM A TO Z
The great split
ActiveRecord MATT YOHO RAILS 3 FROM A TO Z
ActiveRecord ActiveModel ActiveRelation
ActiveModel
ActiveModel :: Validations ActiveModel :: Callbacks ActiveModel :: Errors ActiveModel :: Dirty
validates  :title , :presence   =>  true :format   =>  /[a-zA-Z]/
ActiveModel :: Lint
Mongoid Datamapper
ActiveRelation
Not as speedy?
@tenderlove Comeplete rewrite of Arel
Movie . select( ‘*’ ) where( “title ILIKE %batman%” ). order( ‘release DESC’ )
criteria =  Movie . select( ‘*’ ) where( “title ILIKE %batman%” ). order( ‘release DESC’ )
criteria =  Movie . select( ‘*’ ) where( “title ILIKE %batman%” ). order( ‘release DESC’ )  criteria.to_sql
&quot;SELECT * FROM &quot;movies&quot; WHERE (title ILIKE '%batman%') ORDER BY title&quot;
select() where() order() joins() includes() limit() group() having() etc.
named_scope
scope
scope  :batman_flicks , where( “title ILIKE %batman%” )
default_scope order( “title” )
MATT YOHO RAILS 3 FROM A TO Z Controllers
MATT YOHO RAILS 3 FROM A TO Z ActionController respond_to
MATT YOHO RAILS 3 FROM A TO Z ActionController class   MoviesController  <  ApplicationController   def  show  @movie  =  ...
MATT YOHO RAILS 3 FROM A TO Z ActionController respond_with
MATT YOHO RAILS 3 FROM A TO Z ActionController class   MoviesController  <  ApplicationController respond_to  :json ,  :xm...
MATT YOHO RAILS 3 FROM A TO Z ActionMailer class   Mailer  <  ActionMailer :: Base   default  :from   =>  &quot;invites@mo...
MATT YOHO RAILS 3 FROM A TO Z ActionMailer class   Mailer  <  ActionMailer :: Base   default  :from   =>  &quot;invites@mo...
MATT YOHO RAILS 3 FROM A TO Z mail gem
MATT YOHO RAILS 3 FROM A TO Z ActionMailer :: Base AbstractController::Base ActionController :: Base
Views
Whitelist, not blacklist
<%=  h ( @movie .description)  %>
<%=  @movie .description  %>
<%=  raw( “<h2> #{ @movie .title } </h2>” )  %>
<%=  raw( “<h2> #{ @movie .title } </h2>” )  %> String #html_safe
Unobtrusive JS
link_to_remote  &quot;Destroy&quot; , :url  => movie_url( @movie ), :method  =>  :delete
<a href=&quot;#&quot; onclick=&quot;new Ajax.Request('/movies/4', {asynchronous:true, evalScripts:true, method:'delete'});...
link_to  &quot;Destroy&quot; , movie_url( @movie ), :remote  =>  true , :method  =>  :delete
<a href=&quot;/movies/4&quot; data-remote=”true&quot; data-method=”delete”>Destroy</a> link_to  &quot;Destroy&quot; , movi...
https://github.com/rails/jquery-ujs
Routing
Pneumatic tubes, popular in the late 19th and early 20th century for transporting messages, cash, etc.
Text Resources
CoffeeShop :: Application .routes.draw  do   resources  :cups   do   resources  :shots   end   resources  :coffee_beans en...
cup_shots GET  /cups/:cup_id/shots(.:format)  {:action=>&quot;index&quot;, :controller=>&quot;shots&quot;}  POST  /cups/:c...
cups GET  /cups(.:format)  {:action=>&quot;index&quot;}  POST  /cups(.:format)  {:action=>&quot;create} new_cup GET  /cups...
cups  GET   / cups (.:format)  {:action=>&quot; index &quot;}  POST   / cups (.:format)  {:action=>&quot; create } new_cup...
cups GET  /cups(.:format)  {:action=>&quot;index&quot;}  POST  /cups(.:format)  {:action=>&quot;create} new_cup GET  /cups...
CoffeeShop :: Application .routes.draw  do   resources  :cups   do   resources  :shots   end   resources  :coffee_beans , ...
CoffeeShop :: Application .routes.draw  do   resources  :cups   do   resources  :shots   end   resources  :coffee_beans , ...
CoffeeShop :: Application .routes.draw  do   resources  :cups   do   resources  :shots   end   resources  :coffee_beans , ...
CoffeeShop :: Application .routes.draw  do   resources  :cups   do   resources  :shots   end   resources  :coffee_beans re...
Singular Routes
Movienight :: Application .routes.draw  do   match  &quot;/search&quot; ,  :to  =>  &quot;movies#search&quot; end Simple r...
Movienight :: Application .routes.draw  do   match  &quot;/search&quot; ,  :to  =>  &quot;movies#search&quot; , :as  =>  &...
Movienight :: Application .routes.draw  do   match  &quot;/search&quot; ,  :to  =>  &quot;movies#show&quot; , :via  =>  :g...
Movienight :: Application .routes.draw  do   get  &quot;/search&quot; ,  :to  =>  &quot;movies#search&quot; , :via => :get...
Movienight :: Application .routes.draw  do   root  :to  =>  &quot;nights#index&quot; end Root route
Non-resourceful Methods
CoffeeShop :: Application .routes.draw  do   resources  :coffee_beans   do   collection  do   get  :dark_roast get  :light...
Constraints
Movienight :: Application .routes.draw  do   match  &quot;/search&quot; ,  :constraints  => { :subdomain  =>  &quot;mst3k&...
Movienight :: Application .routes.draw  do   match  &quot;/movies/:imdb_id&quot; ,  :constraints  => { :imdb_id  =>  /d+/ ...
Movienight :: Application .routes.draw  do constraints( :subdomain  =>  &quot;mst3k&quot; )  do   resource  :projector   d...
Optional Segments
# Rails 2 ActionController :: Routing :: Routes .draw  do  | map | map.connect  &quot;/:controller/:action/:id&quot; end  ...
Rack Endpoints
Rack
Movienight :: Application .routes.draw  do   match  &quot;/hello&quot; ,   :to   =>   Proc .new  do  | env | [ 200 , { ‘Co...
Movienight :: Application .routes.draw  do   match  &quot;/hello&quot; ,   :to   =>   Proc .new  do  | env | [ 200 , { ‘Co...
Sinatra MATT YOHO RAILS 3 FROM A TO Z
require  'sinatra/base' class   ApiApp  <  Sinatra :: Base get  &quot;/hello&quot;   do whom = request.cookies[ &quot;whom...
Movienight :: Application .routes.draw  do   scope  &quot;/api&quot;  do   match  &quot;(*path)&quot; ,   :to   =>   ApiAp...
mount
Movienight :: Application .routes.draw  do   mount  ApiApp ,   :at   =>  &quot;/api&quot; end
Special case?
Movienight :: Application .routes.draw  do   match  &quot;/search&quot; ,  :to  =>  &quot;movies#search&quot; end
MoviesController .action( :search ) Movienight :: Application .routes.draw  do   match  &quot;/search&quot; ,  :to  =>  &q...
Movienight :: Application .routes.draw  do   devise_for  :users   resources  :nights   do   resources  :invitations ,  :ex...
Upcoming SlideShare
Loading in...5
×

Rails 3 from A to Z

2,259

Published on

Presentation on fundamentals of Rails and Rails 3 from CodeMash, January 2011.

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,259
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • http://www.flickr.com/photos/tubemail/3002309450/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://yehudakatz.com/2010/02/01/safebuffers-and-rails-3-0/
  • http://www.flickr.com/photos/26666081@N03/5154902507/
  • http://www.flickr.com/photos/dlanod/235990854/
  • http://www.flickr.com/photos/curiousexpeditions/2355395524/
  • http://www.flickr.com/photos/26666081@N03/5154866369/
  • http://www.flickr.com/photos/tubemail/3001472687/
  • http://www.flickr.com/photos/tubemail/3001472687/
  • http://www.flickr.com/photos/tubemail/3001472687/
  • http://www.flickr.com/photos/tubemail/3001472687/
  • http://www.flickr.com/photos/tubemail/3001472687/
  • http://www.flickr.com/photos/curiousexpeditions/2354556261/
  • http://www.flickr.com/photos/sohvimus/3228836603/
  • http://www.flickr.com/photos/sohvimus/3228836603/
  • http://www.flickr.com/photos/danarah/3637584542/
  • http://www.flickr.com/photos/sohvimus/3228836603/
  • http://www.flickr.com/photos/sohvimus/3228836603/
  • Rails 3 from A to Z

    1. 3. @speaker = { :name => ‘Matt Yoho’ , :company => EdgeCase , :writes => [ ‘Ruby on Rails’ ], :loves => [ ‘Comic Books’ ] }
    2. 4. Goals
    3. 5. Rails is a Domain Specific Language for web applications written in and on top of Ruby.
    4. 6. Rails 1.0 December 2005
    5. 7. Rails 2.0 December 2007
    6. 8. Rails 2.3 March 2009
    7. 9. Rails 3 .0 August 2010
    8. 10. Rails 3 .0.3 November 2010
    9. 11. Agenda
    10. 12. 1) Rails Overview
    11. 13. 2) Highlight new features
    12. 14. 3) Example app
    13. 15. Rails concepts
    14. 16. MVC
    15. 17. M odel VC
    16. 18. MV iew C
    17. 19. MV C ontroller
    18. 20. Models Views Controllers Model View Controller
    19. 21. Models Views Controllers Helpers Model View Controller
    20. 22. Models Views Controllers Routes Helpers Model View Controller
    21. 23. class Movie < ActiveRecord :: Base has_many :nights belongs_to :genre validates :title , :presence => true validates :imdb_id , :presence => true , :uniqueness => true before_save :parse_posters def poster_url(size = :thumb ) self .posters.find do | p | p =~ / #{ size } .(jpg|png)Z/i end end end Model Domain logic, CRUD operations. Inherit from ActiveRecord :: Base
    22. 24. Model Domain logic, data persistence. Implement ActiveModel in Rails 3 class Movie < ActiveRecord :: Base has_many :nights belongs_to :genre validates :title , :presence => true validates :imdb_id , :presence => true , :uniqueness => true before_save :parse_posters def poster_url(size = :thumb ) self .posters.find do | p | p =~ / #{ size } .(jpg|png)Z/i end end end
    23. 25. Model Associations Validations Lifecycle callbacks class Movie < ActiveRecord :: Base has_many :nights belongs_to :genre validates :title , :presence => true validates :imdb_id , :presence => true , :uniqueness => true before_save :parse_posters def poster_url(size = :thumb ) self .posters.find do | p | p =~ / #{ size } .(jpg|png)Z/i end end end
    24. 26. < div class= ”movie” > < img src= ” <%= @movie .poster_url %> ” alt= ” <%= @movie .title %> ” /> < h3 ><%= @movie .title %></ h3 > <%= link_to( “See this movie” , movies_path( @movie )) %> </ div > View Presentation templates. Inherit from ActionView :: Base Erb and HAML
    25. 27. View Nested structure. Layouts Templates Partials Partials
    26. 28. View Contain < head > and < body > tags, basic stylesheets and JavaScript links. One or a few per app. Layouts
    27. 29. View Templates Contain page-specific markup and exist for approximately each controller action.
    28. 30. View Small, reusable template components. Partials Partials
    29. 31. class MoviesController < ApplicationController before_filter :user_of_age? def show id = params[ :id ] @movie = Movie .find(id) render ‘movies/show’ end private def user_of_age? unless current_user.age >= 17 redirect_to(root_path) end end end Controller Orchestrators that coordinate data retrieval and persistence, handle request and response bookkeeping, and render views to client. Inherit from ActionController :: Base (In practice, ApplicationController )
    30. 32. Controller Rendering Redirection Filters class MoviesController < ApplicationController before_filter :user_of_age? def show id = params[ :id ] @movie = Movie .find(id) render ‘movies/show’ end private def user_of_age? unless current_user.age >= 17 redirect_to(root_path) end end end
    31. 33. module MoviesHelper def movie_name(night) if night.movie.present? night.movie_title else &quot;DUNNO YET&quot; end end end end Helpers Presentation logic that should be kept out of templates but does not belong on models. Modules, not classes. Presenter models are an alternative.
    32. 34. Movies :: Application .routes.draw do resources :movies do resources :votes , :only => [ :create , :destroy ] end end end Routes Mappings from incoming requests to controller actions (or occasionally elsewhere.) Rails 3 brings new capabilities.
    33. 35. class Notifier < ActionMailer :: Base default :from => &quot;invites@movienight.com&quot; , :subject => &quot;You are invited!&quot; def invited (invitation) headers[ :content_type ] = 'text/html' @night = invitation.night @invitee = invitation.invitee mail :to => invitation.email endend end end Mailer Controller-like classes that render mail messages. Can handle multi-part (plain text/HTML) and attachments. Inherit from ActionMailer::Base
    34. 36. DRY
    35. 37. Don’t Repeat Yourself
    36. 38. class CreateMovies < ActiveRecord :: Migration def self .up create_table :movies do | t | t.string :title t.string :imdb_id t.datetime :release t.text :posters t.timestamps end end def self .down drop_table :movies end end Migrations
    37. 39. class Movie < ActiveRecord :: Base validates :title , :presence => true validates :imdb_id , :presence => true , :uniqueness => true before_save :parse_posters def poster_url( size = :thumb ) self .posters.find do |p| p =~ / #{size} .(jpg|png)Z/i end end end Model
    38. 40. ConventionConfiguration
    39. 41. REST
    40. 42. Define APIs
    41. 43. Define RESTful APIs
    42. 44. Resources
    43. 45. Identified by URIs
    44. 46. http://movienight.com/movies/123
    45. 47. Movie id = 123 ... http://movienight.com/movies/123
    46. 48. May be nested
    47. 49. http://movienight.com/movies/123/actors/4
    48. 50. Movie id = 123 http://movienight.com/movies/123/actors/4 Actor id = 4
    49. 51. May have multiple representations
    50. 52. http://movienight.com/movies/123.json
    51. 53. http://movienight.com/movies/123.json {&quot;movie&quot; : {&quot;alt_title&quot; : &quot;Batman Begins&quot;, &quot;created_at&quot; : &quot;2011-01-07T15:51:50Z&quot;, &quot;id&quot; :33, &quot;imdb_id&quot; : &quot;tt0096251&quot;, &quot;popularity&quot; : 2.0, &quot;posters&quot; : [&quot;http://images.themoviedb.org/posters/1113/poster2rz_thumb.jpg &quot;], &quot;release&quot; : &quot;2005-06-17T00:00:00Z&quot;, &quot;title&quot; : &quot;Batman Begins&quot;, &quot;tmdb_id&quot; : &quot;18393&quot;, &quot;updated_at&quot; : &quot;2011-01-07T15:51:50Z&quot;}} {JSON}
    52. 54. http://movienight.com/movies/123.xml
    53. 55. http://movienight.com/movies/123.xml <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> <movie> <title>Batman Begins</title> <created-at type=&quot;datetime&quot;> 2011-01-06T22:18:44Z </created-at> <id type=&quot;integer&quot;>13</id> <imdb-id>tt0372784</imdb-id> <release type=&quot;datetime&quot;> 2005-06-17T00:00:00Z </release> <tmdb-id>272</tmdb-id> </movie> <xml>
    54. 56. Rely on HTTP content type negotiation
    55. 57. HTTP headers
    56. 58. HTTP headers http://movienight.com/movies/123.json
    57. 59. Accept: application/json, text/javascript, */* ; Request header
    58. 60. Content-Type: application/json; Response header
    59. 61. CRUD via HTTP VERBS
    60. 62. GET POST PUT DELETE HTTP verbs
    61. 63. READ CREATE UPDATE DELETE CRUD operations
    62. 64. SHOW CREATE UPDATE DESTROY Rails controller actions
    63. 65. SHOW CREATE UPDATE DESTROY NEW EDIT INDEX
    64. 66. GET /movies/123 HTTP/1.1 Accept:text/html
    65. 67. GET /movies/123 HTTP/1.1 Accept:text/html CRUD op
    66. 68. GET /movies/123 HTTP/1.1 Accept:text/html Resource
    67. 69. GET /movies/123 HTTP/1.1 Accept:text/html MoviesController#show
    68. 70. Strongly encouraged by Rails
    69. 71. Request -> Response Cycle
    70. 72. Models Views Controllers Routes Request-response cycle Client
    71. 73. Models Views Controllers Routes Request-response cycle Client
    72. 74. Models Views Controllers Routes Request-response cycle Client
    73. 75. Models Views Controllers Routes Request-response cycle Client
    74. 76. Models Views Controllers Routes Request-response cycle Client
    75. 77. Models Views Controllers Routes Request-response cycle Client
    76. 78. Models Views Controllers Routes Request-response cycle Client
    77. 79. Models Views Controllers Routes Request-response cycle Client
    78. 80. Models Views Controllers Routes Request-response cycle Client Webpage!
    79. 81. Feature details
    80. 84. Bundler
    81. 85. Commands
    82. 86. rails new ~/app/name
    83. 87. rails new ~/app/name -T -J
    84. 88. rails new ~/app/name -T -J -T = Skip Test::Unit
    85. 89. rails new ~/app/name -T -J -J = Skip Prototype
    86. 90. rails generate < thing >
    87. 91. rails server
    88. 92. rails console
    89. 93. Dependency Management
    90. 94. can't activate cucumber (= 0.4.4, runtime) for [], already activated cucumber-0.6.1 for [] (Gem::LoadError)
    91. 95. $ gem install rails -v2.3.10Successfully installed activesupport-2.3.9Successfully installed activerecord-2.3.9Successfully installed actionpack-2.3.9Successfully installed actionmailer-2.3.9Successfully installed activeresource-2.3.9Successfully installed rails-2.3.96 gems installed 2.3
    92. 96. $ gem install rails -v3.0.3Successfully installed activesupport-3.0.3Successfully installed builder-2.1.2Successfully installed i18n-0.5.0Successfully installed activemodel-3.0.3Successfully installed rack-1.2.1Successfully installed rack-test-0.5.7Successfully installed rack-mount-0.6.13Successfully installed tzinfo-0.3.23Successfully installed abstract-1.0.0Successfully installed erubis-2.6.6Successfully installed actionpack-3.0.3Successfully installed arel-2.0.6Successfully installed activerecord-3.0.3Successfully installed activeresource-3.0.3Successfully installed mime-types-1.16Successfully installed polyglot-0.3.1Successfully installed treetop-1.4.9Successfully installed mail-2.2.13Successfully installed actionmailer-3.0.3Successfully installed thor-0.14.6Successfully installed railties-3.0.3Successfully installed bundler-1.0.7Successfully installed rails-3.0.323 gems installed 3.0
    93. 97. $ gem install rails -v3.0.3Successfully installed activesupport-3.0.3Successfully installed builder-2.1.2Successfully installed i18n-0.5.0Successfully installed activemodel-3.0.3Successfully installed rack-1.2.1Successfully installed rack-test-0.5.7Successfully installed rack-mount-0.6.13Successfully installed tzinfo-0.3.23Successfully installed abstract-1.0.0Successfully installed erubis-2.6.6Successfully installed actionpack-3.0.3Successfully installed arel-2.0.6Successfully installed activerecord-3.0.3Successfully installed activeresource-3.0.3Successfully installed mime-types-1.16Successfully installed polyglot-0.3.1Successfully installed treetop-1.4.9Successfully installed mail-2.2.13Successfully installed actionmailer-3.0.3Successfully installed thor-0.14.6Successfully installed railties-3.0.3Successfully installed bundler-1.0.7Successfully installed rails-3.0.323 gems installed 3.0
    94. 98. Gemfile
    95. 99. source 'http://rubygems.org' gem 'rails' , '~> 3.0.3' gem 'basic_assumption' , '~> 0.4.1' gem 'devise' , '~> 1.1.5' gem 'dynamic_form' , '~> 1.1.3' gem 'haml' , '~> 3.0.24' gem 'nokogiri' , '~> 1.4.4' gem 'pg' , '~> 0.9.0' gem 'ruby-debug' , '~> 0.10.3' , :platforms => :mri_18 gem 'ruby-debug19' , '~> 0.11.6' , :platforms => :mri_19 group :test do gem 'rspec-rails' , '~> 2.4.1' gem 'factory_girl_rails' , '~> 1.0.0' gem 'fakeweb' , '~> 1.3.0' end end end
    96. 100. source 'http://rubygems.org'
    97. 101. gem 'rails' , '~> 3.0.3'
    98. 102. gem 'rails' , '~> 3.0.3' Name
    99. 103. gem 'rails' , '~> 3.0.3' Version
    100. 104. :mri :mri_18 :mri_19 :mswin :jruby Platforms
    101. 105. gem 'ruby-debug' , :platforms => :mri_18
    102. 106. gem 'ruby-debug19' , :platforms => :mri_19
    103. 107. Install from Git
    104. 108. gem 'basic_assumption' , :git => 'git://github.com/mattyoho/basic_assumption.git' , :branch => 'experimental'
    105. 109. gem 'basic_assumption' , :git => 'git://github.com/mattyoho/basic_assumption.git' , :branch => 'experimental' GitHub repo
    106. 110. gem 'basic_assumption' , :git => 'git://github.com/mattyoho/basic_assumption.git' , :branch => 'experimental' Git repo branch
    107. 111. bundle install
    108. 112. group :test do gem 'rspec-rails' gem 'cucumber' gem 'fakeweb' end end
    109. 113. bundle install --without test
    110. 114. bundle open < gem name >
    111. 115. bundle open < gem name >
    112. 116. bundle update
    113. 117. bundle package
    114. 118. http://gembundler.org/ http://gembundler.com/man/gemfile.5.html
    115. 119. MATT YOHO RAILS 3 FROM A TO Z Models MATT YOHO RAILS 3 FROM A TO Z
    116. 120. The great split
    117. 121. ActiveRecord MATT YOHO RAILS 3 FROM A TO Z
    118. 122. ActiveRecord ActiveModel ActiveRelation
    119. 123. ActiveModel
    120. 124. ActiveModel :: Validations ActiveModel :: Callbacks ActiveModel :: Errors ActiveModel :: Dirty
    121. 125. validates :title , :presence => true :format => /[a-zA-Z]/
    122. 126. ActiveModel :: Lint
    123. 127. Mongoid Datamapper
    124. 128. ActiveRelation
    125. 129. Not as speedy?
    126. 130. @tenderlove Comeplete rewrite of Arel
    127. 131. Movie . select( ‘*’ ) where( “title ILIKE %batman%” ). order( ‘release DESC’ )
    128. 132. criteria = Movie . select( ‘*’ ) where( “title ILIKE %batman%” ). order( ‘release DESC’ )
    129. 133. criteria = Movie . select( ‘*’ ) where( “title ILIKE %batman%” ). order( ‘release DESC’ ) criteria.to_sql
    130. 134. &quot;SELECT * FROM &quot;movies&quot; WHERE (title ILIKE '%batman%') ORDER BY title&quot;
    131. 135. select() where() order() joins() includes() limit() group() having() etc.
    132. 136. named_scope
    133. 137. scope
    134. 138. scope :batman_flicks , where( “title ILIKE %batman%” )
    135. 139. default_scope order( “title” )
    136. 140. MATT YOHO RAILS 3 FROM A TO Z Controllers
    137. 141. MATT YOHO RAILS 3 FROM A TO Z ActionController respond_to
    138. 142. MATT YOHO RAILS 3 FROM A TO Z ActionController class MoviesController < ApplicationController def show @movie = Movie .find(params[:id]) respond_to do | format | format.json { render :json => @movie .to_json } format.xml { render :json => @movie .to_xml } format.html { render ‘movies/show’ } end endend end
    139. 143. MATT YOHO RAILS 3 FROM A TO Z ActionController respond_with
    140. 144. MATT YOHO RAILS 3 FROM A TO Z ActionController class MoviesController < ApplicationController respond_to :json , :xml , :html def show @movie = Movie .find(params[:id]) respond_with( @movie , :status => :ok ) endend end
    141. 145. MATT YOHO RAILS 3 FROM A TO Z ActionMailer class Mailer < ActionMailer :: Base default :from => &quot;invites@movienightapp.com&quot; , :subject => &quot;You’ve been invited to a movie night!&quot; def invitation( invitation ) headers[ :content_type ] = 'text/html' @night , @invitee = invitation.night, invitation.invitee mail :to => invitation.email endend end
    142. 146. MATT YOHO RAILS 3 FROM A TO Z ActionMailer class Mailer < ActionMailer :: Base default :from => &quot;invites@movienightapp.com&quot; , :subject => &quot;You’ve been invited to a movie night!&quot; def invitation( invitation ) headers[ :content_type ] = 'text/html' @night , @invitee = invitation.night, invitation.invitee mail :to => invitation.email endend end message = Mailer .invitation( @invitation ) message.deliver
    143. 147. MATT YOHO RAILS 3 FROM A TO Z mail gem
    144. 148. MATT YOHO RAILS 3 FROM A TO Z ActionMailer :: Base AbstractController::Base ActionController :: Base
    145. 149. Views
    146. 150. Whitelist, not blacklist
    147. 151. <%= h ( @movie .description) %>
    148. 152. <%= @movie .description %>
    149. 153. <%= raw( “<h2> #{ @movie .title } </h2>” ) %>
    150. 154. <%= raw( “<h2> #{ @movie .title } </h2>” ) %> String #html_safe
    151. 155. Unobtrusive JS
    152. 156. link_to_remote &quot;Destroy&quot; , :url => movie_url( @movie ), :method => :delete
    153. 157. <a href=&quot;#&quot; onclick=&quot;new Ajax.Request('/movies/4', {asynchronous:true, evalScripts:true, method:'delete'}); return false;&quot;>Destroy</a> link_to_remote &quot;Destroy&quot; , :url => movie_url( @movie ), :method => :delete
    154. 158. link_to &quot;Destroy&quot; , movie_url( @movie ), :remote => true , :method => :delete
    155. 159. <a href=&quot;/movies/4&quot; data-remote=”true&quot; data-method=”delete”>Destroy</a> link_to &quot;Destroy&quot; , movie_url( @movie ), :remote => true , :method => :delete
    156. 160. https://github.com/rails/jquery-ujs
    157. 161. Routing
    158. 162. Pneumatic tubes, popular in the late 19th and early 20th century for transporting messages, cash, etc.
    159. 163. Text Resources
    160. 164. CoffeeShop :: Application .routes.draw do resources :cups do resources :shots end resources :coffee_beans end end
    161. 165. cup_shots GET /cups/:cup_id/shots(.:format) {:action=>&quot;index&quot;, :controller=>&quot;shots&quot;} POST /cups/:cup_id/shots(.:format) {:action=>&quot;create&quot;, :controller=>&quot;shots&quot;} new_cup_shot GET /cups/:cup_id/shots/new(.:format) {:action=>&quot;new&quot;, :controller=>&quot;shots&quot;} edit_cup_shot GET /cups/:cup_id/shots/:id/edit(.:format) {:action=>&quot;edit&quot;, :controller=>&quot;shots&quot;} cup_shot GET /cups/:cup_id/shots/:id(.:format) {:action=>&quot;show&quot;, :controller=>&quot;shots&quot;} PUT /cups/:cup_id/shots/:id(.:format) {:action=>&quot;update&quot;, :controller=>&quot;shots&quot;} DELETE /cups/:cup_id/shots/:id(.:format) {:action=>&quot;destroy&quot;, :controller=>&quot;shots&quot;} cups GET /cups(.:format) {:action=>&quot;index&quot;, :controller=>&quot;cups&quot;} POST /cups(.:format) {:action=>&quot;create&quot;, :controller=>&quot;cups&quot;} new_cup GET /cups/new(.:format) {:action=>&quot;new&quot;, :controller=>&quot;cups&quot;} edit_cup GET /cups/:id/edit(.:format) {:action=>&quot;edit&quot;, :controller=>&quot;cups&quot;} cup GET /cups/:id(.:format) {:action=>&quot;show&quot;, :controller=>&quot;cups&quot;} PUT /cups/:id(.:format) {:action=>&quot;update&quot;, :controller=>&quot;cups&quot;} DELETE /cups/:id(.:format) {:action=>&quot;destroy&quot;, :controller=>&quot;cups&quot;} coffee_beans GET /coffee_beans(.:format) {:action=>&quot;index&quot;, :controller=>&quot;coffee_beans&quot;} POST /coffee_beans(.:format) {:action=>&quot;create&quot;, :controller=>&quot;coffee_beans&quot;} new_coffee_bean GET /coffee_beans/new(.:format) {:action=>&quot;new&quot;, :controller=>&quot;coffee_beans&quot;}edit_coffee_bean GET /coffee_beans/:id/edit(.:format) {:action=>&quot;edit&quot;, :controller=>&quot;coffee_beans&quot;} coffee_bean GET /coffee_beans/:id(.:format) {:action=>&quot;show&quot;, :controller=>&quot;coffee_beans&quot;} PUT /coffee_beans/:id(.:format) {:action=>&quot;update&quot;, :controller=>&quot;coffee_beans&quot;} DELETE /coffee_beans/:id(.:format) {:action=>&quot;destroy&quot;, :controller=>&quot;coffee_beans&quot;}
    162. 166. cups GET /cups(.:format) {:action=>&quot;index&quot;} POST /cups(.:format) {:action=>&quot;create} new_cup GET /cups/new(.:format) {:action=>&quot;new&quot;}edit_cup GET /cups/:id/edit(.:format) {:action=>&quot;edit&quot;} cup GET /cups/:id(.:format) {:action=>&quot;show&quot;} PUT /cups/:id(.:format) {:action=>&quot;update&quot;} DELETE /cups/:id(.:format) {:action=>&quot;destroy} :controller=>&quot;cups&quot;
    163. 167. cups GET / cups (.:format) {:action=>&quot; index &quot;} POST / cups (.:format) {:action=>&quot; create } new_cup GET /cups/new(.:format) {:action=>&quot;new&quot;}edit_cup GET /cups/:id/edit(.:format) {:action=>&quot;edit&quot;} cup GET /cups/:id(.:format) {:action=>&quot;show&quot;} PUT /cups/:id(.:format) {:action=>&quot;update&quot;} DELETE /cups/:id(.:format) {:action=>&quot;destroy} :controller=>&quot;cups&quot;
    164. 168. cups GET /cups(.:format) {:action=>&quot;index&quot;} POST /cups(.:format) {:action=>&quot;create} new_cup GET /cups/new(.:format) {:action=>&quot;new&quot;}edit_cup GET /cups/:id/edit(.:format) {:action=>&quot;edit&quot;} cup GET / cups/:id (.:format) {:action=>&quot; show &quot;} PUT /cups/:id (.:format) {:action=>&quot; update &quot;} DELETE /cups/:id(.:format) {:action=>&quot;destroy} :controller=>&quot;cups&quot;
    165. 169. CoffeeShop :: Application .routes.draw do resources :cups do resources :shots end resources :coffee_beans , :except => :destroy end end
    166. 170. CoffeeShop :: Application .routes.draw do resources :cups do resources :shots end resources :coffee_beans , :only => [ :new , :show ] end end
    167. 171. CoffeeShop :: Application .routes.draw do resources :cups do resources :shots end resources :coffee_beans , :path_names => [ :edit => ‘brew’ ] end end
    168. 172. CoffeeShop :: Application .routes.draw do resources :cups do resources :shots end resources :coffee_beans resource :shop , :except => [ :destroy ] end
    169. 173. Singular Routes
    170. 174. Movienight :: Application .routes.draw do match &quot;/search&quot; , :to => &quot;movies#search&quot; end Simple routes
    171. 175. Movienight :: Application .routes.draw do match &quot;/search&quot; , :to => &quot;movies#search&quot; , :as => &quot;title_search&quot; end Named routes
    172. 176. Movienight :: Application .routes.draw do match &quot;/search&quot; , :to => &quot;movies#show&quot; , :via => :get end Method-constrained routes
    173. 177. Movienight :: Application .routes.draw do get &quot;/search&quot; , :to => &quot;movies#search&quot; , :via => :get end Method-constrained routes
    174. 178. Movienight :: Application .routes.draw do root :to => &quot;nights#index&quot; end Root route
    175. 179. Non-resourceful Methods
    176. 180. CoffeeShop :: Application .routes.draw do resources :coffee_beans do collection do get :dark_roast get :light_roast end member do put :chew end endend end
    177. 181. Constraints
    178. 182. Movienight :: Application .routes.draw do match &quot;/search&quot; , :constraints => { :subdomain => &quot;mst3k&quot; } end
    179. 183. Movienight :: Application .routes.draw do match &quot;/movies/:imdb_id&quot; , :constraints => { :imdb_id => /d+/ } end
    180. 184. Movienight :: Application .routes.draw do constraints( :subdomain => &quot;mst3k&quot; ) do resource :projector do resources :bmovies end end end
    181. 185. Optional Segments
    182. 186. # Rails 2 ActionController :: Routing :: Routes .draw do | map | map.connect &quot;/:controller/:action/:id&quot; end   # Rails 3 Movienight :: Application .routes.draw do match &quot;/:controller(/:action(/:id))(.:format)&quot; end end end
    183. 187. Rack Endpoints
    184. 188. Rack
    185. 189. Movienight :: Application .routes.draw do match &quot;/hello&quot; , :to => Proc .new do | env | [ 200 , { ‘Content-Type’ => ‘text/plain’ }, [ “Hello, world” ] ] end end
    186. 190. Movienight :: Application .routes.draw do match &quot;/hello&quot; , :to => Proc .new do | env | [ 200 , { ‘Content-Type’ => ‘text/plain’ }, [ “Hello, world” ] ] end end hello /hello(.:format) {:to=>#<Proc:0x00000100f1da28@/app/config/routes.rb:7>}
    187. 191. Sinatra MATT YOHO RAILS 3 FROM A TO Z
    188. 192. require 'sinatra/base' class ApiApp < Sinatra :: Base get &quot;/hello&quot; do whom = request.cookies[ &quot;whom&quot; ] whom ||= &quot;world&quot; set_cookie( ‘whom’ , whom) &quot;Hello, #{ whom } &quot; end post &quot;/hello&quot; do set_cookie( ‘whom’ , params [ :whom ]) redirect &quot;/hello&quot; end end
    189. 193. Movienight :: Application .routes.draw do scope &quot;/api&quot; do match &quot;(*path)&quot; , :to => ApiApp endend end
    190. 194. mount
    191. 195. Movienight :: Application .routes.draw do mount ApiApp , :at => &quot;/api&quot; end
    192. 196. Special case?
    193. 197. Movienight :: Application .routes.draw do match &quot;/search&quot; , :to => &quot;movies#search&quot; end
    194. 198. MoviesController .action( :search ) Movienight :: Application .routes.draw do match &quot;/search&quot; , :to => &quot;movies#search&quot; end
    195. 199. Movienight :: Application .routes.draw do devise_for :users resources :nights do resources :invitations , :except => [ :index , :destroy ], :path_names => { :edit => 'confirm' } end resources :locations , :except => [ :new , :show ] resources :movies do collection do get :title_search end end root :to => &quot;nights#index&quot; end end
    196. 200. Example
    197. 201. Movienight
    198. 202. Resources
    199. 203. http://railsapi.com
    200. 204. Rails for Zombies http://railsforzombies.org /
    201. 205. Rails 3 Cheat Sheets http://blog.envylabs.com/2010/12/rails-3-cheat-sheets/
    202. 206. Rails 3 Upgrade Handbook http://www.railsupgradehandbook.com/

    ×