The slide deck for Andrew White's Technical Breakfast Club, covering how past major releases have tripped people up in upgrades and what strategies you need to adopt to make sure your upgrade path is smooth.
8. 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
9. 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
10. 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
11. 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
13. 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
14. 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
15. ACTION CABLE: ROUGH EDGESACTION CABLE: ROUGH EDGES
Redis required for pubsub
Have to run a second server
Two concurrency models
18. 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
19. 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>
20. 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'] });
21. 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
22. 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
25. SPROCKETS 4: CHANGESSPROCKETS 4: CHANGES
New home – now a Rails organisation project
Source maps
ES6 support via
Many thanks to
Babel
Richard Schneeman
30. 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
31. 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
32. 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
33. 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
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
45. 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
46. 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
47. HOW TO PREPARE?HOW TO PREPARE?
Upgrade to Ruby 2.2.3
Upgrade to Rails 4.2.4
Remove legacy gems
Audit dependencies
48. SUPPORT POLICY: BUG FIXESSUPPORT POLICY: BUG FIXES
Current minor release
Previous minor release
Currently: 4.1 & 4.2
Will be: 4.2 & 5.0
49. 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