Download - Rails 3: Dashing to the Finish
![Page 1: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/1.jpg)
{ Rails 3
![Page 2: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/2.jpg)
![Page 3: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/3.jpg)
Overview
![Page 4: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/4.jpg)
Dashing to the Finish
![Page 5: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/5.jpg)
A Lot Like Rails 2.3
![Page 6: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/6.jpg)
Quick Refresher
![Page 7: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/7.jpg)
What Hasn’t Changed?
![Page 8: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/8.jpg)
MVC
![Page 9: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/9.jpg)
REST
![Page 10: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/10.jpg)
Resources
![Page 11: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/11.jpg)
Controllers
![Page 12: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/12.jpg)
Migrations
![Page 13: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/13.jpg)
AR Ideas
![Page 14: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/14.jpg)
Big User-Facing Changes
![Page 15: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/15.jpg)
File Structure
![Page 16: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/16.jpg)
con!g.ru
# This file is used by Rack-based # servers to start the application.require ::File.expand_path( '../config/environment', __FILE__)run Tutorial::Application
![Page 17: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/17.jpg)
con!g/boot.rb
require 'rubygems'
# Set up gems listed in the Gemfile.gemfile = File.expand_path( '../../Gemfile', __FILE__)if File.exist?(gemfile) ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' Bundler.setupend
![Page 18: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/18.jpg)
Gem!le
source 'http://rubygems.org'
gem 'rails', '3.0.0.beta3'gem 'sqlite3-ruby'
![Page 19: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/19.jpg)
con!g/environment.rb
# Load the rails applicationrequire File.expand_path( '../application', __FILE__)
# Initialize the rails applicationTutorial::Application.initialize!
![Page 20: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/20.jpg)
con!g/application.rb (1)
require File.expand_path( '../boot', __FILE__)
require 'rails/all'
if defined?(Bundler) Bundler.require(:default, Rails.env)end
![Page 21: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/21.jpg)
con!g/application.rb (2)
module Tutorial class Application < Rails::Application config.encoding = "utf-8" config.filter_parameters += [:password] endend
![Page 22: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/22.jpg)
environments/production.rbTutorial::Application.configure do config.cache_classes = true config.consider_all_requests_local = false config.action_controller.perform_caching = true config.action_dispatch.x_sendfile_header = "X-Sendfile" config.serve_static_assets = falseend
![Page 23: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/23.jpg)
initializers/session_store.rb
Rails.application. config.session_store( :cookie_store, :key => '_tutorial_session' )
![Page 24: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/24.jpg)
script/rails (1)#!/usr/bin/env ruby# This command will automatically # be run when you run "rails" with # Rails 3 gems installed from the # root of your application.
ENV_PATH = File.expand_path( '../../config/environment', __FILE__)
![Page 25: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/25.jpg)
script/rails (2)
BOOT_PATH = File.expand_path( '../../config/boot', __FILE__)
APP_PATH = File.expand_path( '../../config/application', __FILE__)
require BOOT_PATHrequire 'rails/commands'
![Page 26: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/26.jpg)
Recent
![Page 27: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/27.jpg)
Even Easier to Remove Bundler
![Page 28: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/28.jpg)
Removing Bundler
$ rm Gemfile
![Page 29: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/29.jpg)
app/mailers
$ script/rails g mailer welcome create app/mailers/welcome.rb invoke erb create app/views/welcome invoke test_unit create test/functional/welcome_test.rb
![Page 30: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/30.jpg)
app/layouts/application.html.erb
<!DOCTYPE html><html> <head> <title>Tutorial</title> <%= stylesheet_link_tag :all %> <%= javascript_include_tag :defaults %> <%= csrf_meta_tag %> </head> <body> <%= yield %> </body></html>
![Page 31: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/31.jpg)
public/javascripts/
rails.js
![Page 32: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/32.jpg)
github.com/rails/jquery-ujs
![Page 33: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/33.jpg)
db/seeds.rb
![Page 34: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/34.jpg)
rake db:setup
![Page 35: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/35.jpg)
db:createdb:schema:load
db:seed
![Page 36: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/36.jpg)
lib/tasks/setup.rake
task :bundle do system "bundle install"end
task :setup => ["bundle", "db:setup"]
![Page 37: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/37.jpg)
Rails Command
★ generate | g
★ console | c
★ server | s
★ dbconsole | db
★ application
★ destroy
★ benchmarker
★ profiler
★ plugin
★ runner
![Page 38: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/38.jpg)
Block Helpers
![Page 39: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/39.jpg)
Block Helpers (Before)
<% form_for @post do |f| %> <%= f.input_field :name %><% end %>
![Page 40: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/40.jpg)
Block Helpers (Before)
<% box do %> <p>Hello World!</p><% end %>
![Page 41: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/41.jpg)
Block Helpers (Before)
def box(&block) content = "<div class='box'>" << capture(&block) << "</div>" if block_called_from_erb? concat(content) else content endend
![Page 42: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/42.jpg)
Block Helpers (After)
<%= box do %> <p>Hello World!</p><% end %>
![Page 43: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/43.jpg)
Block Helpers (After)
def box(&block) "<div class='box'>" \ "#{capture(&block)}" \ "</div>"end
![Page 44: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/44.jpg)
Block Helpers (After)
def box(&block) "<div class='box'>" \ "#{capture(&block)}" \ "</div>".html_safeend
![Page 45: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/45.jpg)
Recent
![Page 46: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/46.jpg)
Tons of Fixes to XSS Safe
![Page 47: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/47.jpg)
Lots of XSS-Related
Changes to Your App...
![Page 48: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/48.jpg)
You’re Doing it Wrong
![Page 49: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/49.jpg)
Router
![Page 50: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/50.jpg)
Note: Signi!cant
Changes Ahead
![Page 51: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/51.jpg)
Also Note: Old Mapper
Still Available
![Page 52: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/52.jpg)
Matching
map.connect "posts", :controller => :posts, :action => :index
![Page 53: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/53.jpg)
Matching
map.connect "posts", :controller => :posts, :action => :index
match "posts" => "posts#index"
![Page 54: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/54.jpg)
Optional Segments
match "/posts(/page)" => "posts#index"
![Page 55: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/55.jpg)
Optional Dynamic Segments
match "/posts(/:id)" => "posts#index"
![Page 56: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/56.jpg)
Default Parameters
match "/posts(/:id)" => "posts#index", :defaults => {:id => 1}
![Page 57: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/57.jpg)
Default Parameters
match "/posts(/:id)" => "posts#index", :id => 1
![Page 58: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/58.jpg)
Named Routes
match "/posts(/:id)" => "posts#index", :id => 1, :as => "posts"
![Page 59: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/59.jpg)
The Root
root :to => "posts#index"
![Page 60: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/60.jpg)
Scopes
![Page 61: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/61.jpg)
Path Scope
match "/admin/posts" => "posts#index"match "/admin/users" => "users#index"
![Page 62: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/62.jpg)
Path Scope
match "/admin/posts" => "posts#index"match "/admin/users" => "users#index"
scope :path => "admin" do match "/posts" => "posts#index" match "/users" => "users#index"end
![Page 63: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/63.jpg)
Path Scope
match "/admin/posts" => "posts#index"match "/admin/users" => "users#index"
scope "admin" do match "/posts" => "posts#index" match "/users" => "users#index"end
![Page 64: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/64.jpg)
Module Scope
match "/posts" => "admin/posts#index"match "/users" => "admin/users#index"
![Page 65: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/65.jpg)
Module Scope
match "/posts" => "admin/posts#index"match "/users" => "admin/users#index"
scope :module => "admin" do match "/posts" => "posts#index" match "/users" => "users#index"end
![Page 66: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/66.jpg)
Both
match "admin/posts" => "admin/posts#index"match "admin/users" => "admin/users#index"
![Page 67: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/67.jpg)
Both
match "admin/posts" => "admin/posts#index"match "admin/users" => "admin/users#index"
namespace "admin" do match "/posts" => "posts#index" match "/users" => "users#index"end
![Page 68: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/68.jpg)
HTTP Methods
![Page 69: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/69.jpg)
Get Request
match "/posts" => "posts#index", :via => "get"
![Page 70: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/70.jpg)
Get Request
match "/posts" => "posts#index", :via => "get"
get "/posts" => "posts#index"
![Page 71: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/71.jpg)
Scoping
scope "/posts" do controller :posts do get "/" => :index endend
![Page 72: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/72.jpg)
Scoping
scope "/posts" do controller :posts do get "/" => :index endend
get "/posts" => "posts#index"
![Page 73: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/73.jpg)
Default Resource Route
controller :posts do scope "/posts" do get "/" => :index post "/" => :create get "/:id" => :show put "/:id" => :update delete "/:id" => :delete get "/new" => :new get "/:id/edit" => :edit endend
![Page 74: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/74.jpg)
Default Resource Routecontroller :posts do scope "/posts" do get "/" => :index, :as => :posts post "/" => :create get "/:id" => :show, :as => :post put "/:id" => :update delete "/:id" => :delete get "/new" => :new, :as => :new_post get "/:id/edit" => :edit, :as => :edit_post endend
![Page 75: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/75.jpg)
Constraints
![Page 76: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/76.jpg)
Regex Constraint
get "/:id" => "posts#index", :constraints => {:id => /\d+/}
![Page 77: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/77.jpg)
Regex Constraint
get "/:id" => "posts#index", :id => /\d+/
![Page 78: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/78.jpg)
Request-Based Constraint
get "/mobile" => "posts#index", :constraints => {:user_agent => /iPhone/}
![Page 79: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/79.jpg)
Request-Based Constraint
get "/mobile" => "posts#index", :constraints => {:user_agent => /iPhone/}, :defaults => {:mobile => true}
![Page 80: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/80.jpg)
Request-Based Constraint
get "/mobile" => "posts#index", :user_agent => /iPhone/, :mobile => true
![Page 81: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/81.jpg)
Object Constraints
class DubDubConstraint def self.matches?(request) request.host =~ /^(www\.)/ endend
get "/" => "posts#index", :constraints => DubDubConstraint
![Page 82: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/82.jpg)
Rack
![Page 83: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/83.jpg)
Equivalent
get "/posts" => "posts#index"
![Page 84: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/84.jpg)
Equivalent
get "/posts" => "posts#index"
get "/posts" => PostsController.action(:index)
![Page 85: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/85.jpg)
Rack
>> a = PostsController.action(:index)
![Page 86: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/86.jpg)
Rack
>> a = PostsController.action(:index)=> #<Proc:0x0000000103d050d0@/Users/wycats/Code/rails/actionpack/lib/action_controller/metal.rb:123>
![Page 87: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/87.jpg)
Rack
>> a = PostsController.action(:index)=> #<Proc:0x0000000103d050d0@/Users/wycats/Code/rails/actionpack/lib/action_controller/metal.rb:123> >> e = Rack::MockRequest.env_for("/")
![Page 88: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/88.jpg)
Rack
>> a = PostsController.action(:index)=> #<Proc:0x0000000103d050d0@/Users/wycats/Code/rails/actionpack/lib/action_controller/metal.rb:123> >> e = Rack::MockRequest.env_for("/")=> {"SERVER_NAME"=>"example.org", "CONTENT_LENGTH"=>"0", ...}
![Page 89: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/89.jpg)
Rack
>> a = PostsController.action(:index)=> #<Proc:0x0000000103d050d0@/Users/wycats/Code/rails/actionpack/lib/action_controller/metal.rb:123> >> e = Rack::MockRequest.env_for("/")=> {"SERVER_NAME"=>"example.org", "CONTENT_LENGTH"=>"0", ...}>> e.call(a)
![Page 90: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/90.jpg)
Rack
>> a = PostsController.action(:index)=> #<Proc:0x0000000103d050d0@/Users/wycats/Code/rails/actionpack/lib/action_controller/metal.rb:123> >> e = Rack::MockRequest.env_for("/")=> {"SERVER_NAME"=>"example.org", "CONTENT_LENGTH"=>"0", ...}>> e.call(a)=> [200, {"ETag"=> '"eca5953f36da05ff351d712d904e"', ...}, ["Hello World"]]
![Page 91: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/91.jpg)
Match to Rack
class MyApp def call(env) [200, {"Content-Type" => "text/html"}, ["Hello World"]] endend
get "/" => MyApp.new
![Page 92: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/92.jpg)
Redirection
get "/" => redirect("/foo")
![Page 93: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/93.jpg)
Redirection
get "/" => redirect("/foo")
get "/:id" => redirect("/posts/%{id}")get "/:id" => redirect("/posts/%s")
![Page 94: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/94.jpg)
Redirection
get "/" => redirect("/foo")
get "/:id" => redirect("/posts/%{id}")get "/:id" => redirect("/posts/%s")
get "/:id" => redirect { |params, req| ...}
![Page 95: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/95.jpg)
Rack Appdef redirect(*args, &block) options = args.last.is_a?(Hash) ? args.pop : {}
path = args.shift || block path_proc = path.is_a?(Proc) ? path : proc { |params| path % params } status = options[:status] || 301 body = 'Moved Permanently'
lambda do |env| req = Request.new(env)
params = [req.symbolized_path_parameters] params << req if path_proc.arity > 1
uri = URI.parse(path_proc.call(*params)) uri.scheme ||= req.scheme uri.host ||= req.host uri.port ||= req.port unless req.port == 80
headers = { 'Location' => uri.to_s, 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s } [ status, headers, [body] ] endend
![Page 96: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/96.jpg)
Rack Appdef redirect(*args, &block) options = args.last.is_a?(Hash) ? args.pop : {}
path = args.shift || block path_proc = path.is_a?(Proc) ? path : proc { |params| path % params } status = options[:status] || 301 body = 'Moved Permanently'
lambda do |env| req = Request.new(env)
params = [req.symbolized_path_parameters] params << req if path_proc.arity > 1
uri = URI.parse(path_proc.call(*params)) uri.scheme ||= req.scheme uri.host ||= req.host uri.port ||= req.port unless req.port == 80
headers = { 'Location' => uri.to_s, 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s } [ status, headers, [body] ] endend
redirect(*args, &block)
![Page 97: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/97.jpg)
Rack Applambda do |env| req = Request.new(env)
params = [req.symbolized_path_parameters] params << req if path_proc.arity > 1
uri = URI.parse(path_proc.call(*params)) uri.scheme ||= req.scheme uri.host ||= req.host uri.port ||= req.port unless req.port == 80
headers = { 'Location' => uri.to_s, 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s } [ status, headers, [body] ]end
![Page 98: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/98.jpg)
Rack Applambda do |env| req = Request.new(env)
params = [req.symbolized_path_parameters] params << req if path_proc.arity > 1
uri = URI.parse(path_proc.call(*params)) uri.scheme ||= req.scheme uri.host ||= req.host uri.port ||= req.port unless req.port == 80
headers = { 'Location' => uri.to_s, 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s } [ status, headers, [body] ]end
[ status, headers, [body] ]
![Page 99: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/99.jpg)
Resources
![Page 100: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/100.jpg)
Resources
resources :magazines do resources :adsend
![Page 101: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/101.jpg)
Member Resources
resources :photos do member do get :preview get :print endend
![Page 102: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/102.jpg)
One-Offs
resources :photos do get :preview, :on => :memberend
![Page 103: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/103.jpg)
Collections
resources :photos do collection do get :search endend
![Page 104: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/104.jpg)
Combination
scope :module => "admin" do constraints IpBlacklist do resources :posts, :comments endend
![Page 105: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/105.jpg)
Recent
![Page 106: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/106.jpg)
#mount
![Page 107: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/107.jpg)
Rack Endpoint
class MountedEndpoint def call(env) head = {"Content-Type" => "text/html"} body = "script: #{env["SCRIPT_NAME"]}" body += "path: #{env["PATH_INFO"]}" [200, head, [body]] endend
![Page 108: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/108.jpg)
Mounting
class MountedEndpoint def call(env) head = {"Content-Type" => "text/html"} body = "script: #{env["SCRIPT_NAME"]}" body += "path: #{env["PATH_INFO"]}" [200, head, [body]] endend
mount "/end", :at => MountedEndpoint.new
![Page 109: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/109.jpg)
Mounting
class MountedEndpoint def call(env) head = {"Content-Type" => "text/html"} body = "script: #{env["SCRIPT_NAME"]}" body += "path: #{env["PATH_INFO"]}" [200, head, [body]] endend
mount "/end", :at => MountedEndpoint.new
# "/end/point" =># script: /end# path: /point
![Page 110: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/110.jpg)
Sinatra!
![Page 111: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/111.jpg)
ActiveRecord
![Page 112: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/112.jpg)
New Chainable, Lazy API
![Page 113: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/113.jpg)
Chainable Methods
★ select★ from★ where★ joins★ having★ group
★ order★ limit★ offset★ includes★ lock★ readonly
![Page 114: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/114.jpg)
Controller
def index @posts = Post. where(:published => true). order("publish_date desc")end
![Page 115: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/115.jpg)
Model
def index @posts = Post.publishedend
class Post < ActiveRecord::Base scope :published, where(:published => true). order("publish_date desc")end
![Page 116: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/116.jpg)
Model
class Post < ActiveRecord::Base scope :desc, order("publish_date desc")
scope :published, where(:published => true).descend
![Page 117: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/117.jpg)
Controller
def index @posts = Post. where("created_at < ?", Time.now). order("publish_date desc")end
![Page 118: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/118.jpg)
Controller
def index @posts = Post.pastend
class Post < ActiveRecord::Base scope :desc, order("publish_date desc")
def self.past where("created_at < ?", Time.now).desc endend
![Page 119: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/119.jpg)
Model
class Post < ActiveRecord::Base scope :desc, order("publish_date desc") def self.past where("created_at < ?", Time.now).desc end
def self.recent(number) past.limit(5) endend
![Page 120: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/120.jpg)
Pagination
class PostsController < ApplicationController def index @posts = Posts.page(5, :per_page => 10) endend
class Post < ActiveRecord::Base def self.page(number, options) per_page = options[:per_page] offset(per_page * (number - 1)). limit(per_page) endend
![Page 121: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/121.jpg)
named_scope
with_scope
!nd(:all)
![Page 122: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/122.jpg)
scope
![Page 123: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/123.jpg)
ActionMailer
![Page 124: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/124.jpg)
Massive API Overhaul
![Page 125: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/125.jpg)
Sending Emails
def welcome(user) @user = user mail(:to => user.email, :subject => "Welcome man!")end
![Page 126: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/126.jpg)
welcome.text.erb
welcome.html.erb
![Page 127: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/127.jpg)
Layouts
layout "rails_dispatch"
def welcome(user) @user = user mail(:to => user.email, :subject => "Welcome man!")end
![Page 128: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/128.jpg)
rails_dispatch.text.erb
rails_dispatch.html.erb
![Page 129: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/129.jpg)
Be More Speci!c
def welcome(user) @user = user mail(:to => user.email, :subject => "Welcome man!") do |format| format.html format.text { render "generic" } endend
![Page 130: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/130.jpg)
Defaults
default :from => "[email protected]"
def welcome(user) @user = user mail(:to => user.email, :subject => "Welcome man!") do |format| format.html format.text { render "generic" } endend
![Page 131: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/131.jpg)
Attachments
def welcome(user) @user = user file = Rails.public_path.join("hello.pdf") contents = File.read(file) attachments["welcome.pdf"] = contents mail(:to => user.email, :subject => "Welcome man!")end
![Page 132: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/132.jpg)
Interceptors
class MyInterceptor def self.delivering_email(mail) original = mail.to mail.to = "[email protected]" mail.subject = "#{original}: #{mail.subject}" endend
![Page 133: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/133.jpg)
Interceptors
class MyInterceptor def self.delivering_email(mail) original = mail.to mail.to = "[email protected]" mail.subject = "#{original}: #{mail.subject}" endend
config.action_mailer. register_interceptor(MyInterceptor)
![Page 134: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/134.jpg)
Interceptors
Delivery
Observers
![Page 135: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/135.jpg)
delivering_mail
deliver
delivered_mail
![Page 136: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/136.jpg)
Bundler
![Page 137: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/137.jpg)
bundle install
![Page 138: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/138.jpg)
bundle lock
![Page 139: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/139.jpg)
bundle lock
![Page 140: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/140.jpg)
.gitignore
.dot!les
![Page 141: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/141.jpg)
Engine YardHeroku
chef
![Page 142: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/142.jpg)
Engine YardHeroku
chefcapistrano?
![Page 143: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/143.jpg)
gembundler.com
![Page 144: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/144.jpg)
gembundler.com/rails3.html
![Page 145: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/145.jpg)
railsdispatch.com/posts/bundler
![Page 146: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/146.jpg)
yehudakatz.com/2010/04/12/some-of-
the-problems-bundler-solves/
![Page 147: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/147.jpg)
yehudakatz.com/2010/04/17/ruby-
require-order-problems/
![Page 148: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/148.jpg)
Choices
![Page 149: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/149.jpg)
rspec-rails
![Page 150: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/150.jpg)
generators
controller_example
view_example
request_example
mailer_example
rake tasks
![Page 151: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/151.jpg)
Mailer Generator
$ script/rails g mailer welcome create app/mailers/welcome.rb invoke erb create app/views/welcome invoke rspec create spec/mailers/welcome_spec.rb
![Page 152: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/152.jpg)
dm-rails
![Page 153: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/153.jpg)
generators
append_info_to_payload
i18n_scope
IdentityMap middleware
rake tasks
![Page 154: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/154.jpg)
generate a resource$ rails g resource comment invoke data_mapper create app/models/comment.rb invoke test_unit create test/unit/comment_test.rb create test/fixtures/comments.yml invoke controller create app/controllers/comments_controller.rb invoke erb create app/views/commentses invoke test_unit create test/functional/comments_controller_test.rb invoke helper create app/helpers/commentses_helper.rb invoke test_unit create test/unit/helpers/comments_helper_test.rb route resources :commentses
![Page 155: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/155.jpg)
generate a resource$ rails g resource comment invoke data_mapper create app/models/comment.rb invoke rspec create spec/models/comment_spec.rb invoke controller create app/controllers/comments_controller.rb invoke erb create app/views/comments invoke rspec create spec/controllers/comments_controller_spec.rb create spec/views/comments invoke helper create app/helpers/comments_helper.rb invoke rspec route resources :comments
![Page 156: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/156.jpg)
rails g$ rails g Rails:
controller generator helper integration_test mailer metal migration model observer performance_test plugin resource scaffold scaffold_controller session_migration stylesheets
![Page 157: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/157.jpg)
What Else?
![Page 158: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/158.jpg)
Ruby 1.9 Encoding
![Page 159: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/159.jpg)
Mission
![Page 160: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/160.jpg)
You Can Assume UTF-8 Inside of Rails
![Page 161: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/161.jpg)
(unless you want to handle
encodings yourself)
![Page 162: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/162.jpg)
Testing
![Page 163: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/163.jpg)
RSpec Driven Effort
![Page 164: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/164.jpg)
Rails Testing Support Becomes Modular
![Page 165: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/165.jpg)
ActionController Middleware
class PostsController use MyMiddleware, :only => :indexend
![Page 166: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/166.jpg)
Metalbecomes
AC::Metal
![Page 167: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/167.jpg)
![Page 168: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/168.jpg)
i18nCheck Out Sven’s Talk
Last slot in conference
![Page 169: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/169.jpg)
Trimming ActiveSupport Dependencies
![Page 170: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/170.jpg)
Thanks!
![Page 171: Rails 3: Dashing to the Finish](https://reader034.vdocuments.site/reader034/viewer/2022052315/5412beec8d7f72314e8b46e1/html5/thumbnails/171.jpg)
Questions?