what’s new in rails 5.0?
TRANSCRIPT
WHAT’S NEW IN RAILS 5WHAT’S NEW IN RAILS 5ANDREW 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 TIMELINERails 1.0: December 2005
Rails 2.0: December 2007
Rails 3.0: August 2010
Rails 4.0: June 2013
Rails 5.0: Autumn 2015
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.rbmodule 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 endend
ACTION CABLE: APPLICATION CHANNEL CLASSACTION CABLE: APPLICATION CHANNEL CLASS# app/channels/application_cable/channel.rbmodule ApplicationCable class Channel < ActionCable::Channel::Base # shared logic between channels endend
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.rbclass 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 endend
ACTION CABLE: SUBSCRIPTION CLASSACTION CABLE: SUBSCRIPTION CLASS# app/assets/javascripts/cable/subscriptions/appearance.coffeeApp.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 EXAMPLEShttp://github.com/rails/actioncable-examples
TURBOLINKS 3: NEW FEATURESTURBOLINKS 3: NEW FEATURESNew 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 ELEMENTSdata-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 REPLACEMENTReplacement 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:2Turbolinks.visit(url, { change: ['comments'] });
// Will change #flash, #comments:1Turbolinks.visit(url, { change: ['comments:1'] });
TURBOLINKS 3: PARTIAL REPLACEMENTTURBOLINKS 3: PARTIAL REPLACEMENTAlso 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 endend
TURBOLINKS 3: PARTIAL REPLACEMENTTURBOLINKS 3: PARTIAL REPLACEMENTBehaviour 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
SPROCKETS 4: CHANGESSPROCKETS 4: CHANGESNew home – now a Rails organisation project
Source maps
ES6 support via
Many thanks to
Babel
Richard Schneeman
RAILS 5: UNDER THE HOODRAILS 5: UNDER THE HOODRuby 2.2 required
Better performanceBetter garbage collectionBetter profiling tools
Focus on performance
Focus on memory usage
https://github.com/rails/rails/pull/21100https://github.com/rails/rails/pull/21411
https://github.com/rails/rails/pull/21057
RAILS 5: CLEANING HOUSERAILS 5: CLEANING HOUSEXML support extracted to gems
Action Mailer*_path helpersdeliver and deliver!
Action PackDOM Assertions:only_path option in *_path helpersstring controller and action keys:to without controller#action:to with a symbol
RAILS 5: CLEANING HOUSERAILS 5: CLEANING HOUSEActive Modelreset_[attribute] and reset_changes
Action RecordBoolean semantics more aligned with RubyTransaction callbacks no longer swallow errorssanitize_sql_hash_for_conditions
Default timestamps columns to null: falseserialized_attributes
Automatic counter caches on has_many :through
RAILS 5: CLEANING HOUSERAILS 5: CLEANING HOUSEActive Support
Default test order is now randomBigDecimal is always encoded as a stringsilence_stderr, silence_stream, capture and quietly
Railtiesrake test:all and rake test:all:db
RAILS 5: CLEANING HOUSERAILS 5: CLEANING HOUSENew deprecations in Active Record for 5.1
Conditions with delete_all and destroy_allActiveRecord::Relation#uniq
Passing a class to whereColumns of type :time will become timezone aware
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTIONActive Record callbacks can now be halted explicitlythrow :abort
New apps get new behaviourUpgraded apps get a deprecation warning
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTIONActionController::Parameters no longer inherits from Hash
Composition over inheritance FTW!No more accidentally calling Enumerable methodsNo more accidentally returning a HashNo more accidentally losing permitted? status
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTIONvalidates_acceptance_of accepts 1 or true
Reversible syntax for change_column_default
# user.rbclass User < ActiveRecord::Base attr_accessor :terms_and_conditions validates_acceptance_of :terms_and_conditionsend
change_column_default(:posts, :state, from: nil, to: "draft")
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTIONAccept 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 REVOLUTIONAdd a http_cache_forever to never expire content
Remove restrictions on partial names
def hello_world http_cache_forever do render text: "Hello, World!" endend
render partial: '! '
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTIONBoot 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 REVOLUTIONBuilt-in support for generating token attributes
Raw model validation errors
class User < ActiveRecord::Base has_secure_tokenend
class User < ActiveRecord::Base validates :name, presence: trueend
user = User.new; user.valid?; user.errors.details=> { name: [{ error: :blank }] }
RAILS 5: EVOLUTION, NOT REVOLUTIONRAILS 5: EVOLUTION, NOT REVOLUTIONweekend? 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 REVOLUTIONInteger#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 5: API ONLY APPLICATIONSRAILS 5: API ONLY APPLICATIONSrails 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 TESTSIntroduced 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 FIXESCurrent minor release
Previous minor release
Currently: 4.1 & 4.2
Will be: 4.2 & 5.0
SUPPORT POLICY: SECURITY UPDATESSUPPORT POLICY: SECURITY UPDATESBug fix releases
Last minor of the previous major
Currently: 3.2, 4.1 & 4.2
Will be: 4.2 & 5.0