Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rails 4.0

Rails 4.0

Presented at @rubymn and MinneBar 2013.


Derek Rockwell

April 06, 2013


  1. @derekrockwell Rails 4.0 and some Ruby 2.0, too

  2. Rails 4 Housekeeping ❖ Extractions, standardizing lifecycle, deprecations Performance ❖

    Queueing, caching, Turbolinks, default threadsafe, streaming New features ❖ PATCH, Concerns, ActiveRecord, Model Ruby 1.9.3 (Ruby 2.0.0 preferred) ❖ Nuff’ said {
  3. None
  4. None
  5. Housekeeping

  6. Pulling things out of Rails ...now with more releases! *you

    can add them back in your Gemfile
  7. Extracted to Gem: • Mass Assignment Protection • Observers/Sweepers •

    Sprockets • Dynamic Finders • Page/Action Caching • ActiveResource • ActiveRecord::SessionStore • Performance tests • Hash-based and Dynamic Finders
  8. Version Policy Standardizing 4.0.0 - simple upgrade from 3.2 4.0.x

    - no new deprecations 4.1.0 - new features, removal of deprecations
  9. Deprecations

  10. config.threadsafe! ...redundant, since Rails defaults to be threadsafe in production

    Rails::Plugin ...no more vendor/plugins, use gems or bundler with path/git routes
  11. Hash based find Rails 4 User.where(created_on: 2.weeks.ago).limit(5) Rails 3 User.find(:all,

    conditions: { created_on: 2.weeks.ago }, limit:5)
  12. Dynamic Finders where(...) where(...).last where(...) where(...).first_or_create where(...).first_or_create! where(...).first_or_initialize find_all_by_... find_last_by_...

    scoped_by_... find_or_create_by_... find_or_initialize_by_... find_or_create_by_...!
  13. Match routes Rails 3 match '/lolcat/:id/memeify', to: 'lolcats#memeify' Rails 4

    match '/lolcat/:id/memeify', to: 'lolcats#memeify', via :post post '/lolcat/:id/memeify', to: 'lolcats#memeify' or... via :get via :put via :delete via :all Also... Generates a bunch of routes. Potential XSS risk!
  14. attr_accessible Rails 3 class User < ActiveRecord::Base attr_accessible :username, :password

    end class UsersController < ApplicationController def create @user = User.create! params[:user] redirect_to @user end end
  15. ...to Strong Parameters Rails 4 class User < ActiveRecord::Base end

    class UsersController < ApplicationController def create @user = User.create! user_params redirect_to @user end private def user_params params.require(:user).permit(:username, :password) end end
  16. Scopes Rails 3 class Blog < ActiveRecord::Base scope :recent, where(created_at:,

    2.weeks.ago) end Rails 4 class Blog < ActiveRecord::Base scope :recent, -> {where(created_at:, 2.weeks.ago)} end
  17. Relation references Rails 3 Post.includes(:comments).where("comments.visible", true) Rails 4 Post.includes(:comments).where("comments.visible", true)

  18. PERFORMANCE “Lie, Cheat and Steal” -Aaron Patterson

  19. ActiveSupport::Queue New Queue Interface: Rails.queue.push Job.new job = Rails.queue.pop job.run

    *Queue interface feature has been pushed back, probably until 4.1
  20. ActiveSupport::Queue Supports many different queue implementations: #new, not yet production

    ready, threaded config.queue = ActiveSupport::Queue.new #new, not yet production ready, synchronous config.queue = ActiveSupport::SynchronousQueue.new config.queue = Resque::Rails::Queue.new config.queue = Sidekiq::Client::Queue.new *Queue interface feature has been pushed back, probably until 4.1
  21. Turbolinks ...frickin’ magic.            user  

           system            total                real  no  turbolinks  11.170000      0.980000    12.460000  (138.656728) yes  turbolinks  10.800000      0.870000    11.670000  (  80.436286)
  22. Turbolinks Pull new versions of title and body with AJAX

  23. Turbolinks gem "turbolinks" //= require turbolinks w.addEventListener( "page:load", function(){ w.picturefill();

    }, false ); *onready isn’t relevant when you are updating the page via AJAX
  24. Turbolinks http://reed.github.com/turbolinks-compatibility/ //= require jquery //= require jquery.turbolinks //= require

    turbolinks <div data-no-turbolink=true id='site_bar'>
  25. ETags

  26. None
  27. ETags They work by using the HTTP_IF_NONE_MATCH and HTTP_IF_MODIFIED_SINCE headers

    to pass back and forth both a unique content identifier and the timestamp of when the content was last changed. If the browser makes a request where the content identifier (etag) or last modified since timestamp matches the server’s version then the server only needs to send back an empty response with a not modified status. Oh. wat wat
  28. ETags Rails 3 • Create response • MD5 response =>

    ETag • Send response and ETag • If ETag matches cached ETag, load page from client cache
  29. ETags Rails server still has to create the response even

    if the client doesn’t use it
  30. ETags Rails 4 class PostsController < ApplicationController def show @post

    = Posts.find(params[:id]) fresh_when(@post) end end
  31. Cache Digests - Fragments <%= cache ['v1', post] do %>

    <%= post %> <%end%> <%= cache ['v2', post] do %> <%= post %> <%end%> <%= cache ['v3', post] do %> <%= post %> <%end%> <%= cache ['v4', post] do %> <%= post %> <%end%> Rails 3 caches changes in the model, but not the template, versioning tracks changes in the template
  32. None
  33. Cache Digests - Fragments <%= cache post do %> <%=

    post %> <%end%> Rails 4 caches also tracks changes in the template, removing the need for versioning
  34. ActiveController:Live Create a chatroom? • Polling for changes • Messaging

    w/ Faye • WebSockets

  36. ActiveController:Live class MessagesController < ApplicationController include ActionController::Live def events response.headers["Content-Type"]

    = "text/event-stream" redis = Redis.new redis.subscribe('messages.create') do |on| on.message do |event, data| response.stream.write("data: #{data}\n\n") end end redis.quit response.stream.close end end def create attributes = params.require(:message).permit(:content, :name) @message = Message.create!(attributes) $redis.publish('messages.create', @message.to_json) end
  37. ActiveController:Live $(document).ready(initialize); function initialize() { var source = new EventSource('/messages/events');

    source.addEventListener('message', update); }; function update(event) { var item = $('<li>').text(event.data); $('#items').append(item); };
  38. ActiveController:Live Caveats: ✤ Code must be thread-safe (Rails4 is thread-safe

    by default) ✤ Write thread-safe code (thread-safe gem, locks) ✤ Web server must support concurrency (e.g. Thin or Puma) in lieu of multi-process servers ✤ Don’t forget to write headers first and close your stream
  39. New Features

  40. Model#none Rails 3 def show_posts if current_user.banned? [] else Post.where(published:

    true) end end if show_posts.any? show_posts.recent else [] end Rails 4 def show_posts if current_user.banned? Post.none else Post.where(published: true) end end show_posts.recent
  41. Relation#not Rails 3 if @author Post.where('author != ?', @author) else

    Post.where('author is not null') end Rails 4 Post.where.not(author: @author)
  42. Concerns Rails3 resources :posts do resources :comments resources :categories resources

    :tags end resources :articles do resources :comments resources :categories resources :tags end Rails4 concern :sociable do resources :comments resources :categories resources :tags end resources :posts, concerns: :sociable resources :articles, concerns: :sociable Extract common model behavior to concerns via new concerns directory
  43. Custom Flash Types class ApplicationController < ActionController::Base add_flash_types :emergency end

    redirect_to @user, emergency: "#openbar" <div class="emergency"> <p><%= emergency %></p> </div>
  44. ActiveModel::Model class Contact include ActiveModel::Model attr_accessor :name, :email, :message validates

    :name, presence: true validates :email, presence: true validates :message, presence: true, length: { maximum: 300 } end def create @contact = Contact.new(params[:contact]) if @contact.valid? ContactMailer.new_contact(@contact).deliver redirect_to root_path else render :new end end
  45. HTML5 Helpers <%= f.date_field :date %> <%= f.month_field :month %>

    <%= f.week_field :week %> <%= f.day_field :day %> <%= f.color_field :color %> <%= f.time_field :time %>
  46. Collection Helpers Rails 3 #create a select box for all

    post authors collection_select(:post, :user_id, User.all, :id, :name) Rails 4 collection_radio_buttons(:post, :user_id, User.all, :id, :name) collection_check_boxes(:post, :user_id, User.all, :id, :name)
  47. Miscellaneous

  48. PostgreSQL type support • arrays • hstore • uuid •

    inet • macaddr • json
  49. PATCH verb http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/ “The HTTP method PUT means resource creation

    or replacement at some given URL” Replaces PUT for update RESTful actions
  50. index.html No more deleting index.html, it is now a dynamic

    route! Add a root entry in routes.rb to override new welcome controller
  51. Filters *_filter actions have been renamed to *_action Rails3 before_filter

    :set_something, except [:delete] Rails4 before_action :set_something, except [:delete] ...backwards compatible
  52. ruby @posts Ruby template handler def index @posts = Posts.all

    respond_to do |format| format.html format.json { render json: @posts } end end #views/posts/index.json.ruby posts_hashes = @owners.map do |owner| { name: owner.author, url: post_url(post) } end posts_hashes.to_json
  53. Test directory changes Rails3 Rails4

  54. Installing $ rvm use ruby-1.9.3@Rails4.0_myapp --create $ gem install rails

    --version 4.0.0.beta1 $ rails new myapp Fair number of major gems have rails4 branches so you can start toying with beta1 today
  55. Fin. 3 Quick Pitches! @derekrockwell

  56. @derekrockwell Rails.MN Community teaching Ruby on Rails to beginners; sponsored

    by CoCo + Google for Entrepreneurs meeting the second Monday of each month
  57. @derekrockwell Ruby.MN User group of Minnesota Rubyists meeting the last

    Monday of each month
  58. Hiring! @derekrockwell Rails developers and designers ...chat with me if

    you’re interested
  59. Thanks! ...Questions? @derekrockwell