WHAT’S NEW IN RAILS 5WHAT’S NEW IN RAILS 5
ANDREW WHITE, CTOANDREW WHITE, CTO
UNBOXED CONSULTINGUNBOXED CONSULTING
WHO AM I?WHO AM I?
GitHub: @pixeltrix
Twitter: @pixeltrix
Contributor since 2007
Committer since 2010
Core Team member since 2012
RAILS TIMELINERAILS TIMELINE
Rails 1.0: December 2005
Rails 2.0: December 2007
Rails 3.0: August 2010
Rails 4.0: June 2013
Rails 5.0: Autumn 2015
DON’T PANIC!DON’T PANIC!
… it’s not going to be like Rails 3.0
ACTION CABLEACTION CABLE
https://github.com/rails/actioncable
WHAT IS IT?WHAT IS IT?
ACTION CABLE: TECHNOLOGY STACKACTION CABLE: TECHNOLOGY STACK
Faye WebSocket for Ruby
Event Machine
Celluloid
Redis
https://github.com/faye/faye-websocket-ruby
https://github.com/eventmachine/eventmachine
https://github.com/celluloid/celluloid
http://redis.io
ACTION CABLE: TERMINOLOGYACTION CABLE: TERMINOLOGY
Channel:
- similar to a controller in MVC
Consumer:
- WebSocket client, typically a browser
Subscriber:
- a consumer that’s connected to a channel
Subscription:
- a connection between the consumer and the channel
ACTION CABLE: PRESENCE EXAMPLEACTION CABLE: PRESENCE EXAMPLE
Create a connection class
Create an application channel class
Connect in the browser
Create a channel class
Create a subscription class
ACTION CABLE: CONNECTION CLASSACTION CABLE: CONNECTION CLASS
# app/channels/application_cable/connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
protected
def find_verified_user
if current_user = User.find(cookies.signed[:user_id])
current_user
else
reject_unauthorized_connection
end
end
end
end
ACTION CABLE: APPLICATION CHANNEL CLASSACTION CABLE: APPLICATION CHANNEL CLASS
# app/channels/application_cable/channel.rb
module ApplicationCable
class Channel < ActionCable::Channel::Base
# shared logic between channels
end
end
ACTION CABLE: CONSUMER CREATIONACTION CABLE: CONSUMER CREATION
# app/assets/javascripts/application_cable.coffee
#= require cable
@App = {}
App.cable = Cable.createConsumer "ws://cable.example.com"
ACTION CABLE: CHANNEL CLASSACTION CABLE: CHANNEL CLASS
# app/channels/appearance_channel.rb
class AppearanceChannel < ApplicationCable::Channel
def subscribed
current_user.appear
end
def unsubscribed
current_user.disappear
end
def appear(data)
current_user.appear on: data['appearing_on']
end
def away
current_user.away
end
end
ACTION CABLE: SUBSCRIPTION CLASSACTION CABLE: SUBSCRIPTION CLASS
# app/assets/javascripts/cable/subscriptions/appearance.coffee
App.appearance = App.cable.subscriptions.create "AppearanceChannel",
connected: ->
# Called once the subscription has been successfully completed
appear: ->
@perform 'appear', appearing_on: @appearingOn()
away: ->
@perform 'away'
appearingOn: ->
$('main').data 'appearing-on'
$(document).on 'page:change', ->
App.appearance.appear()
$(document).on 'click', '[data-behavior~=appear_away]', ->
App.appearance.away()
false
ACTION CABLE: ROUGH EDGESACTION CABLE: ROUGH EDGES
Redis required for pubsub
Have to run a second server
Two concurrency models
FURTHER EXAMPLESFURTHER EXAMPLES
http://github.com/rails/actioncable-examples
TURBOLINKS 3TURBOLINKS 3
https://github.com/rails/turbolinks
TURBOLINKS 3: NEW FEATURESTURBOLINKS 3: NEW FEATURES
New data attributes:
data-turbolinks-permanent
data-turbolinks-temporary
Redirecting uses Turbolinks for XHR and non-GET requests
Progress bar enabled by default
TURBOLINKS 3: PERSISTENT ELEMENTSTURBOLINKS 3: PERSISTENT ELEMENTS
data-turbolinks-permanent
Elements transferred from page to page
Maintains state - ideal for sidebar navigation
Elements must have a unique id attribute
<div id="sidebar" data-turbolinks-permanent="">
Never changes after initial load.
</div>
TURBOLINKS 3: PARTIAL REPLACEMENTTURBOLINKS 3: PARTIAL REPLACEMENT
Replacement based on id or id and data attributes
Match on id prefixes using colon, e.g:
<div id="flash" data-turbolinks-temporary="">
You have 2 comments.
</div>
<ul id="comments">
<li id="comments:1">Hello, World!</li>
<li id="comments:2">Goodbye!</li>
</ul>
// Will change #flash, #comments, #comments:1, #comments:2
Turbolinks.visit(url, { change: ['comments'] });
// Will change #flash, #comments:1
Turbolinks.visit(url, { change: ['comments:1'] });
TURBOLINKS 3: PARTIAL REPLACEMENTTURBOLINKS 3: PARTIAL REPLACEMENT
Also available server-side with redirect_to or render
Replacement based on id or id and data attributes
Use one of change, keep or change options, e.g:
class CommentsController < ActionController::Base
def create
@comment = Comment.new(comment_params)
if @comment.save
redirect_to comments_url, change: 'comments'
else
render :new, change: :new_comment
end
end
end
TURBOLINKS 3: PARTIAL REPLACEMENTTURBOLINKS 3: PARTIAL REPLACEMENT
Behaviour of render and redirect_to options:
# Refresh any `data-turbolinks-temporary` nodes and
# nodes with `id` matching `new_comment`.
render view, change: 'new_comment'
# Refresh any `data-turbolinks-temporary` nodes and nodes
# with `id` not matching `something` and `something:*`.
render view, keep: 'something'
# Replace the entire `body` of the document,
# including `data-turbolinks-permanent` nodes.
render view, flush: true
GIVE IT A TRY…GIVE IT A TRY…
SPROCKETS 4SPROCKETS 4
https://github.com/rails/sprockets
SPROCKETS 4: CHANGESSPROCKETS 4: CHANGES
New home – now a Rails organisation project
Source maps
ES6 support via
Many thanks to
Babel
Richard Schneeman
RAILS 5RAILS 5
https://github.com/rails/rails
UNDER THE HOODUNDER THE HOOD
RAILS 5: UNDER THE HOODRAILS 5: UNDER THE HOOD
Ruby 2.2 required
Better performance
Better garbage collection
Better profiling tools
Focus on performance
Focus on memory usage
https://github.com/rails/rails/pull/21100
https://github.com/rails/rails/pull/21411
https://github.com/rails/rails/pull/21057
CLEANING HOUSECLEANING HOUSE
RAILS 5: CLEANING HOUSERAILS 5: CLEANING HOUSE
XML support extracted to gems
Action Mailer
*_path helpers
deliver and deliver!
Action Pack
DOM Assertions
:only_path option in *_path helpers
string controller and action keys
:to without controller#action
:to with a symbol
RAILS 5: CLEANING HOUSERAILS 5: CLEANING HOUSE
Active Model
reset_[attribute] and reset_changes
Action Record
Boolean semantics more aligned with Ruby
Transaction callbacks no longer swallow errors
sanitize_sql_hash_for_conditions
Default timestamps columns to null: false
serialized_attributes
Automatic counter caches on has_many :through
RAILS 5: CLEANING HOUSERAILS 5: CLEANING HOUSE
Active Support
Default test order is now random
BigDecimal is always encoded as a string
silence_stderr, silence_stream, capture and quietly
Railties
rake test:all and rake test:all:db
RAILS 5: CLEANING HOUSERAILS 5: CLEANING HOUSE
New deprecations in Active Record for 5.1
Conditions with delete_all and destroy_all
ActiveRecord::Relation#uniq
Passing a class to where
Columns of type :time will become timezone aware
EVOLUTION, NOTEVOLUTION, NOT
REVOLUTIONREVOLUTION
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
Active Record callbacks can now be halted explicitly
throw :abort
New apps get new behaviour
Upgraded apps get a deprecation warning
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
ActionController::Parameters no longer inherits from Hash
Composition over inheritance FTW!
No more accidentally calling Enumerable methods
No more accidentally returning a Hash
No more accidentally losing permitted? status
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
validates_acceptance_of accepts 1 or true
Reversible syntax for change_column_default
# user.rb
class User < ActiveRecord::Base
attr_accessor :terms_and_conditions
validates_acceptance_of :terms_and_conditions
end
change_column_default(:posts, :state, from: nil, to: "draft")
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
Accept a collection in fresh_when and stale?
expands to:
def index
@article = Article.all
fresh_when(@articles)
end
def index
@article = Article.all
fresh_when(etag: @articles, last_modified: @articles.maximum(:updated_at))
end
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
Add a http_cache_forever to never expire content
Remove restrictions on partial names
def hello_world
http_cache_forever do
render text: "Hello, World!"
end
end
render partial: '! '
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
Boot rails s in development with caching enabled
Non-request context rendering
rails s --dev-caching
ApplicationController.render template: 'foo/bar'
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
Built-in support for generating token attributes
Raw model validation errors
class User < ActiveRecord::Base
has_secure_token
end
class User < ActiveRecord::Base
validates :name, presence: true
end
user = User.new; user.valid?; user.errors.details
=> { name: [{ error: :blank }] }
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
weekend? query method for date and time
next_weekday for next working day
prev_weekday for previous working day
Date.current.weekend?
=> false
Date.current.end_of_week.next_weekday
=> Mon, 21 Sep 2015
Date.current.beginning_of_week.prev_weekday
=> Fri, 11 Sep 2015
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION
Integer#positive? and Integer#negative?
Built-in support for method.source_code
rails is now the command hub, e.g:
>> Object.new.method(:blank?).source_code
def blank?
respond_to?(:empty?) ? !!empty? : !self
end
rails db:migrate
RAILS APIRAILS API
It’s coming home, it’s coming home …
RAILS 5: API ONLY APPLICATIONSRAILS 5: API ONLY APPLICATIONS
rails new my_api --api
Limited middleware stack
ApplicationController < ActionController::API
Still has essentials like CSRF and HTTP caching
By default uses Active Model Serializers for output
INTEGRATION TESTSINTEGRATION TESTS
Introduced in Rails 1.1
Confusion between controller and integration tests
Controller tests to become integration tests (TBC)
Performance improvements means no cost
Assertions for assigns and rendered templates removed
HOW TO PREPARE?HOW TO PREPARE?
Upgrade to Ruby 2.2.3
Upgrade to Rails 4.2.4
Remove legacy gems
Audit dependencies
SUPPORT POLICY: BUG FIXESSUPPORT POLICY: BUG FIXES
Current minor release
Previous minor release
Currently: 4.1 & 4.2
Will be: 4.2 & 5.0
SUPPORT POLICY: SECURITY UPDATESSUPPORT POLICY: SECURITY UPDATES
Bug fix releases
Last minor of the previous major
Currently: 3.2, 4.1 & 4.2
Will be: 4.2 & 5.0
Q & AQ & A

What’s New in Rails 5.0?

  • 1.
    WHAT’S NEW INRAILS 5WHAT’S NEW IN RAILS 5 ANDREW WHITE, CTOANDREW WHITE, CTO UNBOXED CONSULTINGUNBOXED CONSULTING
  • 2.
    WHO AM I?WHOAM I? GitHub: @pixeltrix Twitter: @pixeltrix Contributor since 2007 Committer since 2010 Core Team member since 2012
  • 3.
    RAILS TIMELINERAILS TIMELINE Rails1.0: December 2005 Rails 2.0: December 2007 Rails 3.0: August 2010 Rails 4.0: June 2013 Rails 5.0: Autumn 2015
  • 4.
    DON’T PANIC!DON’T PANIC! …it’s not going to be like Rails 3.0
  • 5.
  • 6.
  • 7.
    ACTION CABLE: TECHNOLOGYSTACKACTION CABLE: TECHNOLOGY STACK Faye WebSocket for Ruby Event Machine Celluloid Redis https://github.com/faye/faye-websocket-ruby https://github.com/eventmachine/eventmachine https://github.com/celluloid/celluloid http://redis.io
  • 8.
    ACTION CABLE: TERMINOLOGYACTIONCABLE: TERMINOLOGY Channel: - similar to a controller in MVC Consumer: - WebSocket client, typically a browser Subscriber: - a consumer that’s connected to a channel Subscription: - a connection between the consumer and the channel
  • 9.
    ACTION CABLE: PRESENCEEXAMPLEACTION CABLE: PRESENCE EXAMPLE Create a connection class Create an application channel class Connect in the browser Create a channel class Create a subscription class
  • 10.
    ACTION CABLE: CONNECTIONCLASSACTION CABLE: CONNECTION CLASS # app/channels/application_cable/connection.rb module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = find_verified_user end protected def find_verified_user if current_user = User.find(cookies.signed[:user_id]) current_user else reject_unauthorized_connection end end end end
  • 11.
    ACTION CABLE: APPLICATIONCHANNEL CLASSACTION CABLE: APPLICATION CHANNEL CLASS # app/channels/application_cable/channel.rb module ApplicationCable class Channel < ActionCable::Channel::Base # shared logic between channels end end
  • 12.
    ACTION CABLE: CONSUMERCREATIONACTION CABLE: CONSUMER CREATION # app/assets/javascripts/application_cable.coffee #= require cable @App = {} App.cable = Cable.createConsumer "ws://cable.example.com"
  • 13.
    ACTION CABLE: CHANNELCLASSACTION CABLE: CHANNEL CLASS # app/channels/appearance_channel.rb class AppearanceChannel < ApplicationCable::Channel def subscribed current_user.appear end def unsubscribed current_user.disappear end def appear(data) current_user.appear on: data['appearing_on'] end def away current_user.away end end
  • 14.
    ACTION CABLE: SUBSCRIPTIONCLASSACTION CABLE: SUBSCRIPTION CLASS # app/assets/javascripts/cable/subscriptions/appearance.coffee App.appearance = App.cable.subscriptions.create "AppearanceChannel", connected: -> # Called once the subscription has been successfully completed appear: -> @perform 'appear', appearing_on: @appearingOn() away: -> @perform 'away' appearingOn: -> $('main').data 'appearing-on' $(document).on 'page:change', -> App.appearance.appear() $(document).on 'click', '[data-behavior~=appear_away]', -> App.appearance.away() false
  • 15.
    ACTION CABLE: ROUGHEDGESACTION CABLE: ROUGH EDGES Redis required for pubsub Have to run a second server Two concurrency models
  • 16.
  • 17.
  • 18.
    TURBOLINKS 3: NEWFEATURESTURBOLINKS 3: NEW FEATURES New data attributes: data-turbolinks-permanent data-turbolinks-temporary Redirecting uses Turbolinks for XHR and non-GET requests Progress bar enabled by default
  • 19.
    TURBOLINKS 3: PERSISTENTELEMENTSTURBOLINKS 3: PERSISTENT ELEMENTS data-turbolinks-permanent Elements transferred from page to page Maintains state - ideal for sidebar navigation Elements must have a unique id attribute <div id="sidebar" data-turbolinks-permanent=""> Never changes after initial load. </div>
  • 20.
    TURBOLINKS 3: PARTIALREPLACEMENTTURBOLINKS 3: PARTIAL REPLACEMENT Replacement based on id or id and data attributes Match on id prefixes using colon, e.g: <div id="flash" data-turbolinks-temporary=""> You have 2 comments. </div> <ul id="comments"> <li id="comments:1">Hello, World!</li> <li id="comments:2">Goodbye!</li> </ul> // Will change #flash, #comments, #comments:1, #comments:2 Turbolinks.visit(url, { change: ['comments'] }); // Will change #flash, #comments:1 Turbolinks.visit(url, { change: ['comments:1'] });
  • 21.
    TURBOLINKS 3: PARTIALREPLACEMENTTURBOLINKS 3: PARTIAL REPLACEMENT Also available server-side with redirect_to or render Replacement based on id or id and data attributes Use one of change, keep or change options, e.g: class CommentsController < ActionController::Base def create @comment = Comment.new(comment_params) if @comment.save redirect_to comments_url, change: 'comments' else render :new, change: :new_comment end end end
  • 22.
    TURBOLINKS 3: PARTIALREPLACEMENTTURBOLINKS 3: PARTIAL REPLACEMENT Behaviour of render and redirect_to options: # Refresh any `data-turbolinks-temporary` nodes and # nodes with `id` matching `new_comment`. render view, change: 'new_comment' # Refresh any `data-turbolinks-temporary` nodes and nodes # with `id` not matching `something` and `something:*`. render view, keep: 'something' # Replace the entire `body` of the document, # including `data-turbolinks-permanent` nodes. render view, flush: true
  • 23.
    GIVE IT ATRY…GIVE IT A TRY…
  • 24.
  • 25.
    SPROCKETS 4: CHANGESSPROCKETS4: CHANGES New home – now a Rails organisation project Source maps ES6 support via Many thanks to Babel Richard Schneeman
  • 26.
  • 27.
  • 28.
    RAILS 5: UNDERTHE HOODRAILS 5: UNDER THE HOOD Ruby 2.2 required Better performance Better garbage collection Better profiling tools Focus on performance Focus on memory usage https://github.com/rails/rails/pull/21100 https://github.com/rails/rails/pull/21411 https://github.com/rails/rails/pull/21057
  • 29.
  • 30.
    RAILS 5: CLEANINGHOUSERAILS 5: CLEANING HOUSE XML support extracted to gems Action Mailer *_path helpers deliver and deliver! Action Pack DOM Assertions :only_path option in *_path helpers string controller and action keys :to without controller#action :to with a symbol
  • 31.
    RAILS 5: CLEANINGHOUSERAILS 5: CLEANING HOUSE Active Model reset_[attribute] and reset_changes Action Record Boolean semantics more aligned with Ruby Transaction callbacks no longer swallow errors sanitize_sql_hash_for_conditions Default timestamps columns to null: false serialized_attributes Automatic counter caches on has_many :through
  • 32.
    RAILS 5: CLEANINGHOUSERAILS 5: CLEANING HOUSE Active Support Default test order is now random BigDecimal is always encoded as a string silence_stderr, silence_stream, capture and quietly Railties rake test:all and rake test:all:db
  • 33.
    RAILS 5: CLEANINGHOUSERAILS 5: CLEANING HOUSE New deprecations in Active Record for 5.1 Conditions with delete_all and destroy_all ActiveRecord::Relation#uniq Passing a class to where Columns of type :time will become timezone aware
  • 34.
  • 35.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION Active Record callbacks can now be halted explicitly throw :abort New apps get new behaviour Upgraded apps get a deprecation warning
  • 36.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION ActionController::Parameters no longer inherits from Hash Composition over inheritance FTW! No more accidentally calling Enumerable methods No more accidentally returning a Hash No more accidentally losing permitted? status
  • 37.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION validates_acceptance_of accepts 1 or true Reversible syntax for change_column_default # user.rb class User < ActiveRecord::Base attr_accessor :terms_and_conditions validates_acceptance_of :terms_and_conditions end change_column_default(:posts, :state, from: nil, to: "draft")
  • 38.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION Accept a collection in fresh_when and stale? expands to: def index @article = Article.all fresh_when(@articles) end def index @article = Article.all fresh_when(etag: @articles, last_modified: @articles.maximum(:updated_at)) end
  • 39.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION Add a http_cache_forever to never expire content Remove restrictions on partial names def hello_world http_cache_forever do render text: "Hello, World!" end end render partial: '! '
  • 40.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION Boot rails s in development with caching enabled Non-request context rendering rails s --dev-caching ApplicationController.render template: 'foo/bar'
  • 41.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION Built-in support for generating token attributes Raw model validation errors class User < ActiveRecord::Base has_secure_token end class User < ActiveRecord::Base validates :name, presence: true end user = User.new; user.valid?; user.errors.details => { name: [{ error: :blank }] }
  • 42.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION weekend? query method for date and time next_weekday for next working day prev_weekday for previous working day Date.current.weekend? => false Date.current.end_of_week.next_weekday => Mon, 21 Sep 2015 Date.current.beginning_of_week.prev_weekday => Fri, 11 Sep 2015
  • 43.
    RAILS 5: EVOLUTION,NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTION Integer#positive? and Integer#negative? Built-in support for method.source_code rails is now the command hub, e.g: >> Object.new.method(:blank?).source_code def blank? respond_to?(:empty?) ? !!empty? : !self end rails db:migrate
  • 44.
    RAILS APIRAILS API It’scoming home, it’s coming home …
  • 45.
    RAILS 5: APIONLY APPLICATIONSRAILS 5: API ONLY APPLICATIONS rails new my_api --api Limited middleware stack ApplicationController < ActionController::API Still has essentials like CSRF and HTTP caching By default uses Active Model Serializers for output
  • 46.
    INTEGRATION TESTSINTEGRATION TESTS Introducedin Rails 1.1 Confusion between controller and integration tests Controller tests to become integration tests (TBC) Performance improvements means no cost Assertions for assigns and rendered templates removed
  • 47.
    HOW TO PREPARE?HOWTO PREPARE? Upgrade to Ruby 2.2.3 Upgrade to Rails 4.2.4 Remove legacy gems Audit dependencies
  • 48.
    SUPPORT POLICY: BUGFIXESSUPPORT POLICY: BUG FIXES Current minor release Previous minor release Currently: 4.1 & 4.2 Will be: 4.2 & 5.0
  • 49.
    SUPPORT POLICY: SECURITYUPDATESSUPPORT POLICY: SECURITY UPDATES Bug fix releases Last minor of the previous major Currently: 3.2, 4.1 & 4.2 Will be: 4.2 & 5.0
  • 50.
    Q & AQ& A