{   Rails 3
Overview
A Lot Like
Rails 2.3
Quick Refresher
What Hasn’t
 Changed?
MVC
REST
Resources
Controllers
Migrations
AR Ideas
Big User-Facing
   Changes
File Structure
con g.ru
# This file is used by Rack-based
# servers to start the application.

require ::File.expand_path(
  '../config/e...
con g/boot.rb
require 'rubygems'

# Set up gems listed in the Gemfile.
gemfile = File.expand_path(
  '../../Gemfile',
  __...
Gem le
source 'http://rubygems.org'

gem 'rails', '3.0.0.beta3'
gem 'sqlite3-ruby',
    :require => 'sqlite3'
con g/environment.rb
# Load the rails application
require File.expand_path(
  '../application',
  __FILE__
)

# Initialize...
con g/application.rb (1)
require File.expand_path(
  '../boot',
  __FILE__
)

require 'rails/all'

if defined?(Bundler)
  ...
con g/application.rb (2)
module Tutorial
  class Application < Rails::Application
    config.encoding = "utf-8"
    config...
environments/production.rb
Tutorial::Application.configure do
  config.cache_classes = true
  config.consider_all_requests...
initializers/session_store.rb
Rails.application.
  config.session_store(
    :cookie_store,
    :key => '_tutorial_session...
script/rails (1)
#!/usr/bin/env ruby
# This command will automatically
# be run when you run "rails" with
# Rails 3 gems i...
script/rails (2)
BOOT_PATH = File.expand_path(
  '../../config/boot',
  __FILE__
)

APP_PATH = File.expand_path(
  '../../...
app/mailers
$ script/rails g mailer welcome
  create app/mailers/welcome.rb
  invoke erb
  create    app/views/welcome
  i...
app/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
  <title>Tutorial</title>
  <%= stylesheet_link_tag :all %>...
public/
javascripts/
   rails.js
github.com/
rails/jquery-ujs
db/seeds.rb
rake db:setup
db:create
db:schema:load
    db:seed
lib/tasks/setup.rake
task :bundle do
  system "bundle install"
end

task :setup => ["bundle", "db:setup"]
Rails Command

★ generate   | g   ★ destroy
★ console    | c   ★ benchmarker
★ server     | s   ★ profiler
★ dbconsole | d...
Block Helpers
Block Helpers (Before)
<% form_for @post do |f| %>
<% end %>
Block Helpers (Before)
<% box do %>
  <p>Hello World!</p>
<% end %>
Block Helpers (Before)
def box(&block)
  content = "<div class='box'>" <<
    capture(&block) << "</div>"

  if block_call...
Block Helpers (After)
<%= box do %>
  <p>Hello World!</p>
<% end %>
Block Helpers (After)
def box(&block)
  "<div class='box'>" 
  "#{capture(&block)}" 
  "</div>"
end
Block Helpers (After)
def box(&block)
  "<div class='box'>" 
  "#{capture(&block)}" 
  "</div>".html_safe
end
Router
Note:
  Signi cant
Changes Ahead
Also Note:
 Old Mapper
Still Available
Matching
map.connect "posts",
  :controller => :posts,
  :action => :index
Matching
map.connect "posts",
  :controller => :posts,
  :action => :index

match "posts" => "posts#index"
Matching
map.connect "posts",
  :controller => :posts,
  :action => :index

match "/posts" => "posts#index"
Optional Segments
match "/posts(/page)" => "posts#index"
Optional Dynamic Segments
match "/posts(/:id)" => "posts#index"
Default Parameters
match "/posts(/:id)" => "posts#index",
      :defaults => {:id => 1}
Default Parameters
match "/posts(/:id)" => "posts#index",
      :id => 1
Named Routes
match "/posts(/:id)" => "posts#index",
      :id => 1,
      :as => "posts"
The Root
root :to => "posts#index"
Scopes
Path Scope
match "/admin/posts" => "posts#index"
match "/admin/users" => "users#index"
Path Scope
scope :path => "admin" do
  match "/posts" => "posts#index"
  match "/users" => "users#index"
end
Path Scope
scope "admin" do
  match "/posts" => "posts#index"
  match "/users" => "users#index"
end
Module Scope
match "/posts" => "admin/posts#index"
match "/users" => "admin/users#index"
Module Scope
scope :module => "admin" do
  match "/posts" => "posts#index"
  match "/users" => "users#index"
end
Both
match "admin/posts" => "admin/posts#index"
match "admin/users" => "admin/users#index"
Both
namespace "admin" do
  match "/posts" => "posts#index"
  match "/users" => "users#index"
end
HTTP Methods
Get Request
match "/posts" => "posts#index",
      :via => "get"
Get Request
get "/posts" => "posts#index"
Scoping
scope "/posts" do
  controller :posts do
    get "/" => :index
  end
end
Scoping
get "/posts" => "posts#index"
Default Resource Route
controller :posts do
  scope "/posts" do
    get    "/"          =>   :index
    post   "/"        ...
Default Resource Route
controller :posts do
  scope "/posts" do
    get    "/"           =>   :index,   :as => :posts
    ...
Constraints
Regex Constraint
get "/:id" => "posts#index",
  :constraints => {:id => /d+/}
Regex Constraint
get "/:id" => "posts#index",
    :id => /d+/
Request-Based Constraint
get "/mobile" => "posts#index",
  :constraints => {:user_agent => /iPhone/}
Request-Based Constraint
get "/mobile" => "posts#index",
  :constraints => {:user_agent => /iPhone/},
  :defaults    => {:...
Request-Based Constraint
get "/mobile" => "posts#index",
  :user_agent => /iPhone/,
  :mobile     => true
Object Constraints
class DubDubConstraint
  def self.matches?(request)
    request.host =~ /^(www.)/
  end
end

get "/" =>...
Rack
Equivalent
get "/posts" => "posts#index"

get "/posts" =>
    PostsController.action(:index)
Rack
>> a = PostsController.action(:index)
Rack
>> a = PostsController.action(:index)
=> #<Proc:0x0000000103d050d0@/Users/
wycats/Code/rails/actionpack/lib/
action_c...
Rack
>> a = PostsController.action(:index)
=> #<Proc:0x0000000103d050d0@/Users/
wycats/Code/rails/actionpack/lib/
action_c...
Rack
>> a = PostsController.action(:index)
=> #<Proc:0x0000000103d050d0@/Users/
wycats/Code/rails/actionpack/lib/
action_c...
Rack
>> a = PostsController.action(:index)
=> #<Proc:0x0000000103d050d0@/Users/
wycats/Code/rails/actionpack/lib/
action_c...
Rack
>> a = PostsController.action(:index)
=> #<Proc:0x0000000103d050d0@/Users/
wycats/Code/rails/actionpack/lib/
action_c...
Match to Rack
class MyApp
  def call(env)
    [200,
      {"Content-Type" => "text/html"},
      ["Hello World"]]
  end
en...
Redirection
get "/" => redirect("/foo")
Redirection
get "/" => redirect("/foo")

get "/:id" => redirect("/posts/%{id}")
get "/:id" => redirect("/posts/%s")
Redirection
get "/" => redirect("/foo")

get "/:id" => redirect("/posts/%{id}")
get "/:id" => redirect("/posts/%s")

get "...
Rack App
def redirect(*args, &block)
  options = args.last.is_a?(Hash) ? args.pop : {}

  path        =   args.shift || bl...
Rack App
def redirect(*args, &block)
  options = args.last.is_a?(Hash) ? args.pop : {}

  path        =   args.shift || bl...
Rack App
lambda do |env|
  req = Request.new(env)

  params = [req.symbolized_path_parameters]
  params << req if path_pro...
Resources
Resources
resources :magazines do
  resources :ads
end
Member Resources
resources :photos do
  member do
    get :preview
    get :print
  end
end
One-Offs
resources :photos do
  get :preview, :on => :member
end
Collections
resources :photos do
  collection do
    get :search
  end
end
Combination
scope :module => "admin" do
  constraints IpBlacklist do
    resources :posts, :comments
  end
end
ActiveRecord
New Chainable,
  Lazy API
Chainable Methods

★ select        ★ order
★ from          ★ limit
★ where         ★ offset
★ joins         ★ includes
★ h...
Controller
def index
  @posts = Post.
    where(:published => true).
    order("publish_date desc")
end
Model
scope :published,
  where(:published => true).
  order("publish_date desc")
Model
scope :desc,
  order("publish_date desc")

scope :published,
  where(:published => true).desc
Controller
def index
  @posts = Post.
    where("created_at < ?", Time.now).
    order("publish_date desc")
end
Model
scope :desc,
  order("publish_date desc")

def self.past
  where("created_at < ?",
    Time.now).desc
end
Model
scope :desc,
  order("publish_date desc")

def self.past
  where("created_at < ?",
    Time.now).desc
end

def self....
Pagination
class PostsController
  def index
    @posts = Posts.page(5, :per_page => 10)
  end
end

class Post < ActiveRec...
named_scope

with_scope

   nd(:all)
scope
ActionMailer
Massive API
 Overhaul
Sending Emails
def welcome(user)
  @user = user
  mail(:to => user.email,
       :subject => "Welcome man!")
end
welcome.text.erb

welcome.html.erb
Layouts
layout "rails_dispatch"

def welcome(user)
  @user = user
  mail(:to => user.email,
       :subject => "Welcome ma...
rails_dispatch.text.erb

rails_dispatch.html.erb
Be More Speci c
def welcome(user)
  @user = user
  mail(:to => user.email,
  :subject => "Welcome man!") do |format|
    f...
Defaults
default :from => "wycats@gmail.com"

def welcome(user)
  @user = user
  mail(:to => user.email,
  :subject => "We...
Attachments
def welcome(user)
  @user = user

  file = Rails.public_path.join("hello.pdf")
  contents = File.readfile)
  a...
Interceptors
class MyInterceptor
  def self.delivering_email(mail)
    original = mail.to
    mail.to = "wycats@gmail.com"...
Interceptors
class MyInterceptor
  def self.delivering_email(mail)
    original = mail.to
    mail.to = "wycats@gmail.com"...
Interceptors

 Delivery

 Observers
delivering_mail

    deliver

delivered_mail
Bundler
gembundler.com
gembundler.com
  /rails3.html
railsdispatch.com
 /posts/bundler
yehudakatz.com/
2010/04/12/some-of-
   the-problems-
   bundler-solves/
yehudakatz.com/
2010/04/17/ruby-
 require-order-
   problems/
Choices
rspec-rails
generators

    rake tasks

controller_example

  view_example

request_example

 mailer_example
Mailer Generator
$ script/rails g mailer welcome
  create app/mailers/welcome.rb
  invoke erb
  create    app/views/welcom...
dm-rails
generators

      rake tasks

append_info_to_payload

      i18n_scope

IdentityMap middleware
generate a resource
$ rails g resource comment
  invoke data_mapper
  create    app/models/comment.rb
  invoke    test_uni...
generate a resource
$ rails g resource comment
  invoke data_mapper
  create    app/models/comment.rb
  invoke    rspec
  ...
rails g
$ rails g                     stylesheets

Rails:                      DataMapper:
  controller                  d...
Rails 3 overview
Rails 3 overview
Rails 3 overview
Rails 3 overview
Rails 3 overview
Upcoming SlideShare
Loading in...5
×

Rails 3 overview

6,769

Published on

Published in: Technology
0 Comments
26 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,769
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
273
Comments
0
Likes
26
Embeds 0
No embeds

No notes for slide

Rails 3 overview

  1. 1. { Rails 3
  2. 2. Overview
  3. 3. A Lot Like Rails 2.3
  4. 4. Quick Refresher
  5. 5. What Hasn’t Changed?
  6. 6. MVC
  7. 7. REST
  8. 8. Resources
  9. 9. Controllers
  10. 10. Migrations
  11. 11. AR Ideas
  12. 12. Big User-Facing Changes
  13. 13. File Structure
  14. 14. 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
  15. 15. 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.setup end
  16. 16. Gem le source 'http://rubygems.org' gem 'rails', '3.0.0.beta3' gem 'sqlite3-ruby', :require => 'sqlite3'
  17. 17. con g/environment.rb # Load the rails application require File.expand_path( '../application', __FILE__ ) # Initialize the rails application Tutorial::Application.initialize!
  18. 18. con g/application.rb (1) require File.expand_path( '../boot', __FILE__ ) require 'rails/all' if defined?(Bundler) Bundler.require(:default, Rails.env) end
  19. 19. con g/application.rb (2) module Tutorial class Application < Rails::Application config.encoding = "utf-8" config.filter_parameters += [:password] end end
  20. 20. environments/production.rb Tutorial::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 = false end
  21. 21. initializers/session_store.rb Rails.application. config.session_store( :cookie_store, :key => '_tutorial_session' )
  22. 22. 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__ )
  23. 23. script/rails (2) BOOT_PATH = File.expand_path( '../../config/boot', __FILE__ ) APP_PATH = File.expand_path( '../../config/application', __FILE__ ) require BOOT_PATH require 'rails/commands'
  24. 24. 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
  25. 25. 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>
  26. 26. public/ javascripts/ rails.js
  27. 27. github.com/ rails/jquery-ujs
  28. 28. db/seeds.rb
  29. 29. rake db:setup
  30. 30. db:create db:schema:load db:seed
  31. 31. lib/tasks/setup.rake task :bundle do system "bundle install" end task :setup => ["bundle", "db:setup"]
  32. 32. Rails Command ★ generate | g ★ destroy ★ console | c ★ benchmarker ★ server | s ★ profiler ★ dbconsole | db ★ plugin ★ application ★ runner
  33. 33. Block Helpers
  34. 34. Block Helpers (Before) <% form_for @post do |f| %> <% end %>
  35. 35. Block Helpers (Before) <% box do %> <p>Hello World!</p> <% end %>
  36. 36. Block Helpers (Before) def box(&block) content = "<div class='box'>" << capture(&block) << "</div>" if block_called_from_erb? concat(content) else content end end
  37. 37. Block Helpers (After) <%= box do %> <p>Hello World!</p> <% end %>
  38. 38. Block Helpers (After) def box(&block) "<div class='box'>" "#{capture(&block)}" "</div>" end
  39. 39. Block Helpers (After) def box(&block) "<div class='box'>" "#{capture(&block)}" "</div>".html_safe end
  40. 40. Router
  41. 41. Note: Signi cant Changes Ahead
  42. 42. Also Note: Old Mapper Still Available
  43. 43. Matching map.connect "posts", :controller => :posts, :action => :index
  44. 44. Matching map.connect "posts", :controller => :posts, :action => :index match "posts" => "posts#index"
  45. 45. Matching map.connect "posts", :controller => :posts, :action => :index match "/posts" => "posts#index"
  46. 46. Optional Segments match "/posts(/page)" => "posts#index"
  47. 47. Optional Dynamic Segments match "/posts(/:id)" => "posts#index"
  48. 48. Default Parameters match "/posts(/:id)" => "posts#index", :defaults => {:id => 1}
  49. 49. Default Parameters match "/posts(/:id)" => "posts#index", :id => 1
  50. 50. Named Routes match "/posts(/:id)" => "posts#index", :id => 1, :as => "posts"
  51. 51. The Root root :to => "posts#index"
  52. 52. Scopes
  53. 53. Path Scope match "/admin/posts" => "posts#index" match "/admin/users" => "users#index"
  54. 54. Path Scope scope :path => "admin" do match "/posts" => "posts#index" match "/users" => "users#index" end
  55. 55. Path Scope scope "admin" do match "/posts" => "posts#index" match "/users" => "users#index" end
  56. 56. Module Scope match "/posts" => "admin/posts#index" match "/users" => "admin/users#index"
  57. 57. Module Scope scope :module => "admin" do match "/posts" => "posts#index" match "/users" => "users#index" end
  58. 58. Both match "admin/posts" => "admin/posts#index" match "admin/users" => "admin/users#index"
  59. 59. Both namespace "admin" do match "/posts" => "posts#index" match "/users" => "users#index" end
  60. 60. HTTP Methods
  61. 61. Get Request match "/posts" => "posts#index", :via => "get"
  62. 62. Get Request get "/posts" => "posts#index"
  63. 63. Scoping scope "/posts" do controller :posts do get "/" => :index end end
  64. 64. Scoping get "/posts" => "posts#index"
  65. 65. 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 end end
  66. 66. Default Resource Route controller :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 end end
  67. 67. Constraints
  68. 68. Regex Constraint get "/:id" => "posts#index", :constraints => {:id => /d+/}
  69. 69. Regex Constraint get "/:id" => "posts#index", :id => /d+/
  70. 70. Request-Based Constraint get "/mobile" => "posts#index", :constraints => {:user_agent => /iPhone/}
  71. 71. Request-Based Constraint get "/mobile" => "posts#index", :constraints => {:user_agent => /iPhone/}, :defaults => {:mobile => true}
  72. 72. Request-Based Constraint get "/mobile" => "posts#index", :user_agent => /iPhone/, :mobile => true
  73. 73. Object Constraints class DubDubConstraint def self.matches?(request) request.host =~ /^(www.)/ end end get "/" => "posts#index", :constraints => DubDubConstraint
  74. 74. Rack
  75. 75. Equivalent get "/posts" => "posts#index" get "/posts" => PostsController.action(:index)
  76. 76. Rack >> a = PostsController.action(:index)
  77. 77. Rack >> a = PostsController.action(:index) => #<Proc:0x0000000103d050d0@/Users/ wycats/Code/rails/actionpack/lib/ action_controller/metal.rb:123>
  78. 78. Rack >> a = PostsController.action(:index) => #<Proc:0x0000000103d050d0@/Users/ wycats/Code/rails/actionpack/lib/ action_controller/metal.rb:123> >> e = Rack::MockRequest.env_for("/")
  79. 79. 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", ...}
  80. 80. 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)
  81. 81. 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"=> ‘"eca5953f36da05ff351d712d904ef28d"’, ...}
  82. 82. Match to Rack class MyApp def call(env) [200, {"Content-Type" => "text/html"}, ["Hello World"]] end end get "/" => MyApp
  83. 83. Redirection get "/" => redirect("/foo")
  84. 84. Redirection get "/" => redirect("/foo") get "/:id" => redirect("/posts/%{id}") get "/:id" => redirect("/posts/%s")
  85. 85. Redirection get "/" => redirect("/foo") get "/:id" => redirect("/posts/%{id}") get "/:id" => redirect("/posts/%s") get "/:id" => redirect { |params, req| ... }
  86. 86. Rack App def 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] ] end end
  87. 87. Rack App def 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) redirect(*args, &block) 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 end
  88. 88. Rack App 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] ] end
  89. 89. Resources
  90. 90. Resources resources :magazines do resources :ads end
  91. 91. Member Resources resources :photos do member do get :preview get :print end end
  92. 92. One-Offs resources :photos do get :preview, :on => :member end
  93. 93. Collections resources :photos do collection do get :search end end
  94. 94. Combination scope :module => "admin" do constraints IpBlacklist do resources :posts, :comments end end
  95. 95. ActiveRecord
  96. 96. New Chainable, Lazy API
  97. 97. Chainable Methods ★ select ★ order ★ from ★ limit ★ where ★ offset ★ joins ★ includes ★ having ★ lock ★ group ★ readonly
  98. 98. Controller def index @posts = Post. where(:published => true). order("publish_date desc") end
  99. 99. Model scope :published, where(:published => true). order("publish_date desc")
  100. 100. Model scope :desc, order("publish_date desc") scope :published, where(:published => true).desc
  101. 101. Controller def index @posts = Post. where("created_at < ?", Time.now). order("publish_date desc") end
  102. 102. Model scope :desc, order("publish_date desc") def self.past where("created_at < ?", Time.now).desc end
  103. 103. Model scope :desc, order("publish_date desc") def self.past where("created_at < ?", Time.now).desc end def self.recent(number) past.limit(5) end
  104. 104. Pagination class PostsController def index @posts = Posts.page(5, :per_page => 10) end end class Post < ActiveRecord::Base def self.page(number, options) per_page = options[:per_page] offset(per_page * (number - 1)). limit(per_page) end end
  105. 105. named_scope with_scope nd(:all)
  106. 106. scope
  107. 107. ActionMailer
  108. 108. Massive API Overhaul
  109. 109. Sending Emails def welcome(user) @user = user mail(:to => user.email, :subject => "Welcome man!") end
  110. 110. welcome.text.erb welcome.html.erb
  111. 111. Layouts layout "rails_dispatch" def welcome(user) @user = user mail(:to => user.email, :subject => "Welcome man!") end
  112. 112. rails_dispatch.text.erb rails_dispatch.html.erb
  113. 113. Be More Speci c def welcome(user) @user = user mail(:to => user.email, :subject => "Welcome man!") do |format| format.html format.text { render "generic" } end end
  114. 114. Defaults default :from => "wycats@gmail.com" def welcome(user) @user = user mail(:to => user.email, :subject => "Welcome man!") do |format| format.html format.text { render "generic" } end end
  115. 115. Attachments def welcome(user) @user = user file = Rails.public_path.join("hello.pdf") contents = File.readfile) attachments["welcome.pdf"] = contents mail(:to => user.email, :subject => "Welcome man!") end
  116. 116. Interceptors class MyInterceptor def self.delivering_email(mail) original = mail.to mail.to = "wycats@gmail.com" mail.subject = "#{original}: #{mail.subject}" end end
  117. 117. Interceptors class MyInterceptor def self.delivering_email(mail) original = mail.to mail.to = "wycats@gmail.com" mail.subject = "#{original}: #{mail.subject}" end end config.action_mailer. register_interceptor(MyInterceptor)
  118. 118. Interceptors Delivery Observers
  119. 119. delivering_mail deliver delivered_mail
  120. 120. Bundler
  121. 121. gembundler.com
  122. 122. gembundler.com /rails3.html
  123. 123. railsdispatch.com /posts/bundler
  124. 124. yehudakatz.com/ 2010/04/12/some-of- the-problems- bundler-solves/
  125. 125. yehudakatz.com/ 2010/04/17/ruby- require-order- problems/
  126. 126. Choices
  127. 127. rspec-rails
  128. 128. generators rake tasks controller_example view_example request_example mailer_example
  129. 129. 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
  130. 130. dm-rails
  131. 131. generators rake tasks append_info_to_payload i18n_scope IdentityMap middleware
  132. 132. 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
  133. 133. 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
  134. 134. rails g $ rails g stylesheets Rails: DataMapper: controller data_mapper:migration generator data_mapper:model helper data_mapper:observer integration_test mailer Rspec: metal rspec:controller migration rspec:helper model rspec:install observer rspec:integration performance_test rspec:mailer plugin rspec:model resource rspec:observer scaffold rspec:scaffold scaffold_controller rspec:view session_migration
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×