Rails 2.3
Brian Turnbull http://brianturnbull.com
Templates rails app rails app’ template rails app -m template.rb rails app -m http://example.com/template rake rails:template LOCATION=template.rb
Templates # template.rb gem "hpricot" rake "gems:install" run "rm public/index.html" generate :scaffold, "person name:string" route "map.root :controller => 'people'" rake "db:migrate" git :init git :add => "." git :commit => "-a -m 'Initial commit'"
Pratik Naik — http://m.onkey.org/2008/12/4/rails-templates
Templates Jeremy McAnally’s Template Library http://github.com/jeremymcanally/rails-templates/tree/master
Engines Rails Plugins turned to Eleven Share Models, Views, and Controllers with Host App Share Routes with Host App
http://rails-engines.org/news/2009/02/02/engines-in-rails-2-3/
Engines Not Yet Fully Baked Manually Manage Migrations Manually Merge Public Assets
http://rails-engines.org/news/2009/02/02/engines-in-rails-2-3/
Nested Transactions User.transaction do User.create(:username => 'Admin') User.transaction(:requires_new => true) do User.create(:username => 'Regular') raise ActiveRecord::Rollback end end User.find(:all)
# => Returns only Admin
http://guides.rubyonrails.org/2_3_release_notes.html
Nested Attributes class Book < ActiveRecord::Base has_one :author has_many :pages accepts_nested_attributes_for :author, :pages end
http://guides.rubyonrails.org/2_3_release_notes.html
Nested Forms class Book < ActiveRecord::Base has_many :authors accepts_nested_attributes_for :authors end <% form_for @book do |book_form| %>
<%= book_form.label :title, 'Book Title:' %> <%= book_form.text_field :title %>
<% book_form.fields_for :authors do |author_form| %>
<%= author_form.label :name, 'Author Name:' %> <%= author_form.text_field :name %>
<% end %> <% end %> <%= book_form.submit %> <% end %>
http://guides.rubyonrails.org/2_3_release_notes.html
Dynamic and Default Scopes ## id Integer ## customer_id Integer ## status String ## entered_at DateTime class Order < ActiveRecord::Base belongs_to :customer default_scope :order => 'entered_at' end Order.scoped_by_customer_id(12) Order.scoped_by_customer_id(12).find(:all, :conditions => "status = 'open'") Order.scoped_by_customer_id(12).scoped_by_status("open")
http://guides.rubyonrails.org/2_3_release_notes.html
Other Changes Multiple Conditions for Callbacks HTTP Digest Authentication Lazy Loaded Sessions Localized Views and More!
http://guides.rubyonrails.org/2_3_release_notes.html
Rails 2.3
Rails Metal
SPEED Simplicity
Metal Endpoint ## app/metal/hello_metal.rb class HelloMetal def self.call(env) if env["PATH_INFO"] =~ /^\/hello\/metal/ [200, {"Content-Type" => "text/plain"}, ["Hello, Metal!"]] else [404, {"Content-Type" => "text/html"}, ["Not Found"]] end end end
http://soylentfoo.jnewland.com/articles/2008/12/16/rails-metal-a-micro-framework-with-the-power-of-rails-m
Equivalent Controller ## app/controllers/hello_rails_controller.rb class HelloRailsController < ApplicationController def show headers['Content-Type'] = 'text/plain' render :text => 'Hello, Rails!' end end
http://soylentfoo.jnewland.com/articles/2008/12/16/rails-metal-a-micro-framework-with-the-power-of-rails-m
Sinatra! require 'sinatra' Sinatra::Application.set(:run => false) Sinatra::Application.set(:environment => :production) HelloSinatra = Sinatra::Application.new unless defined? HelloSinatra get '/hello/sinatra' do response['Content-Type'] = 'text/plain' 'Hello, Sinatra!' end
http://soylentfoo.jnewland.com/articles/2008/12/16/rails-metal-a-micro-framework-with-the-power-of-rails-m
Rack Object.call(env)
[status, headers, response]
Metal Endpoint ## app/metal/hello_metal.rb class HelloMetal def self.call(env) if env["PATH_INFO"] =~ /^\/hello\/metal/ [200, {"Content-Type" => "text/plain"}, ["Hello, Metal!"]] else [404, {"Content-Type" => "text/html"}, ["Not Found"]] end end end
Rack Middleware in Rails Rails Dispatcher call(env)
[s,h,r]
Middleware call(env)
[s,h,r]
Middleware call(env)
[s,h,r]
Web Server
Rack Middleware in Rails % rake middleware use Rack::Lock use ActionController::Failsafe use ActionController::Session::CookieStore use Rails::Rack::Metal use ActionController::RewindableInput use ActionController::ParamsParser use Rack::MethodOverride use Rack::Head use ActiveRecord::QueryCache run ActionController::Dispatcher.new
Rack Middleware in Rails % rake middleware use Rack::Lock use ActionController::Failsafe use ActionController::Session::CookieStore use Rails::Rack::Metal use ActionController::RewindableInput use ActionController::ParamsParser use Rack::MethodOverride use Rack::Head use ActiveRecord::QueryCache run ActionController::Dispatcher.new
Django > Rails? ## lib/middleware/django_middleware.rb class DjangoMiddleware def initialize(app) @app = app end def call(env) status, headers, response = @app.call(env) new_response = [] response.each do |part| new_response << part.gsub(/Rails/, 'Django') end [status, headers, new_response] end end ## config/environment.rb config.middleware.use DjangoMiddleware
http://github.com/bturnbull/bturnbull-metal-demo