I give a run-down of some of the latest features in Rails slated for the 4.0 release, and tips on how to prepare your Rails 3 app for upcoming changes.
STRONG PARAMETERS class PeopleController < ApplicationController def create @person = Person.create(params[:person]) end end class Person < ActiveRecord::Base attr_accessible :name, :age end In Rails 3: Thursday, February 7, 13
STRONG PARAMETERS class PeopleController < ApplicationController def create @person = Person.create(person_params) end private def person_params params.require(:person).permit(:name, :age) end end Use in Rails 3 Today: https://github.com/rails/strong_parameters In Rails 4: Thursday, February 7, 13
LIVE STREAMING class MyController < ActionController::Base include ActionController::Live def stream response.headers['Content-Type'] = 'text/event-stream' 100.times { response.stream.write "hello world\n" sleep 1 } response.stream.close end end Thursday, February 7, 13
LIVE STREAMING CAVEATS • Actions run in separate thread; controller action code must be thread save! • Concurrent Ruby Server Required (puma, rainbows!, thin) • Headers must be written before anything else • Streams must be closed http://tenderlovemaking.com/2012/07/30/is-it-live.html Thursday, February 7, 13
POSTGRES ARRAY SUPPORT class AddTagsToArticles < ActiveRecord::Migration def change change_table :articles do |t| t.string :tags, array: true end end end article.tags = ['rails'] article.save # UPDATE "articles" SET "tags" = '{"rails"}' # WHERE "articles"."id" = 1 HStore Support New Data Types Support Thursday, February 7, 13
AREL .FIRST / .LAST In Rails 3: Calling .first or .last was indeterminate (DB-specific). In Rails 4: Calling .first or .last defaults to using ORDER BY id. Thursday, February 7, 13
AREL .NONE @posts = current_user.visible_posts.where(:name => params[:name]) def visible_posts case role if 'Country Manager' Post.where(:country => country) if 'Reviewer' Post.published if 'Bad User' # returning [] instead breaks the previous code; not chainable Post.where("1=0") end end In Rails 3: Thursday, February 7, 13
AREL .NONE @posts = current_user.visible_posts.where(:name => params[:name]) def visible_posts case role if 'Country Manager' Post.where(:country => country) if 'Reviewer' Post.published if 'Bad User' # returning [] instead breaks the previous code; not chainable Post.none end end In Rails 4: Thursday, February 7, 13
AREL BANG! METHODS class PeopleController < ApplicationController def index @people = People.active @people = @people.where(:first_name => params[:first_name]) if params[:last_name].present? @people = @people.where(:last_name => params[:last_name]) if params[:last_name].present? end end In Rails 3: Thursday, February 7, 13
AREL BANG! METHODS class PeopleController < ApplicationController def index @people = People.active @people.where!(:first_name => params[:first_name]) if params[:last_name].present? @people.where!(:last_name => params[:last_name]) if params[:last_name].present? end end In Rails 4: Thursday, February 7, 13
ROUTING CONCERNS Penguin::Application.routes.draw do resources :projects do resources :comments end resources :tasks do resources :comments end resources :articles do resources :comments end end In Rails 3: Thursday, February 7, 13
ROUTING CONCERNS In Rails 4: Penguin::Application.routes.draw do concern :commentable do resources :comments end resources :projects, concerns: :commentable resources :tasks, concerns: :commentable resources :articles, concerns: :commentable end Use in Rails 3 Today: https://github.com/rails/routing_concerns Thursday, February 7, 13
FRAGMENT CACHE DIGESTS # app/views/todolists/_todolist.html.erb <% cache todolist do %> My todolist: <%= todolist.name %> <%= render document.comments %> <% end %> # app/views/comments/_comment.html.erb <% cache comment do %> My comment: <%= comment.body %> <% end %> In Rails 3: Thursday, February 7, 13
FRAGMENT CACHE DIGESTS # app/views/todolists/_todolist.html.erb <% cache todolist do %> My todolist: <%= todolist.name %> <%= render document.comments %> <% end %> # app/views/comments/_comment.html.erb <% cache comment do %> My comment: <%= comment.body %> <% end %> In Rails 4: Thursday, February 7, 13
PATCH, NOT PUT RFC 5789 technically describes PATCH as a partial update, what everyone is using PUT for today. Default for update will now be PATCH. https://github.com/rails/rails/pull/505 Thursday, February 7, 13
PLAY WITH RAILS 4 NOW $ git clone http://github.com/rails/rails.git $ cd rails && bundle install $ ruby railties/bin/rails new ../try_four --dev $ cd ../try_four Thursday, February 7, 13