4/9/2019 - 11:22 PM

Upgrading Rails

Ugrading from 4.2 to 5.0

  • Rails 5.0 requires ruby version 2.2.2+
    • Current version: 2.3.1
  • All models inherit from ApplicationRecord
    • Create app/models/application_record.rb with the following code:
    class ApplicationRecord < ActiveRecord::Base
      self.abstract_class = true
    • Make sure all your models inherit from it!
  • before callbacks would return false in ActiveRecord and ActiveModel and thereby halting the entire execution chain.
    • Callback chains must be explicitly halted by calling throw(:abort)
    • Add to config/application.rb: ActiveSupport.halt_callback_chains_on_return_false = false
  • ActiveJob now inherits from ApplicationJob
    • Create app/jobs/application_job.rb add the following code
    class ApplicationJob < ActiveJob::Base
    • Make sure all job classes inherit from it.
  • If using assigns and assert_template in controller tests add gem 'rails-controller-testing' to gemfile
  • Uploading files using ActionDispatch::Http::UploadFile replace with Rack::Test::UploadedFile
  • Autoloading is now disabled after booting in Production Environment, if need to be set use: Rails.application.config.enable_dependency_loading = true
  • ActiveModel::Serializers::Xml has been extracted into a gem: gem 'activemodel-serializers-xml'
  • Support for mysql has been removed, use mysql2
  • Use rails instead of rake for running tasks and tests
  • Calling params will now return an object instead of a hash.
    • If using params.permit then no changes are needed.
    • Otherwise, you will need to convert params.permit([:proceed_to, :return_to]).to_h
  • protect_from_forgery defaults to prepend: false
  • Default template handler is now RAW. Always specify the extension of your file to be parsed by an appropriate template handler
  • Add wildcard for template dependencies
  • content_tag_for and div_for have been removed in favor of just using content_tag, to continue using the older view helper methods add the gem gem 'record_tag_helper', '~> 1.0' to gemfile
  • The protected_attributes gem is no longer supported in Rails 5!
  • The activerecord-deprecated_finders gem is no longer supported in Rails 5!
  • Test cases are now ran randomly instead of sorted, to revert to sorted:
# config/environments/test.rb
Rails.application.configure do
  config.active_support.test_order = :sorted
  • ActionController::Live became a concern!
    • If ActionController::Live is included in another module that is included in your controller, then you should extend the module with ActiveSupport::Concern

Framework Defaults

  • belongs_to will now trigger a validation error by default if there is no association present
    • Can be turned off per association by using : optional: true
    • For all associations, place LOC inside an initializer: config.active_record.belongs_to_required_by_default = true
  • Per-form CSRF tokens: when activated every form in your app will each have their own CSRF token that is specific to that action and method for that form: config.action_controller.per_form_csrf_tokens = true
  • For additional CSRF protection, you can configure your app to check if the HTTP Origin header should be checked against the site's origin: config.action_controller.forgery_protection_origin_check = true
  • Default mailer queue name is mailers, you can change it with this configuration: config.action_mailer.deliver_later_queue_name = :new_queue_name
  • Support for fragment caching in your config: config.action_mailer.perform_caching = true
  • Control how the schema is dumped: config.active_record.dump_schemas = :all
  • Configure SSL options to enable HSTS with subdomains: config.ssl_options = { hsts: { subdomains: true } }
  • Ruby 2.4: allows you to preserve the timezone of the reciever: ActiveSupport.to_time_preserves_timezone = false
  • It is recommended that you do not set columns equal to a String, but pass a Hash instead, which will be converted to and from a JSON string automatically

Ugrading from 5.0 to 5.1

  • If app uses HashWithIndifferentAccess class, move to using ActiveSupport::HashWithIndifferentAccess
  • In config/secrets.yml all keys are now loaded as symbols, using strings should be changed!

Ugrading from 5.1 to 5.2

  • Rails 5.2 adds bootsnap gem (which reduces boot time of app)
    • app:update sets it up in boot.rb, use it then add to gemfile
    • No need to use it then change the boot.rb
  • Expiry info is imbedded in ecrypted or signed cookies, which makes the cookies incompatible with Rails older than 5.2
    • If you require cookies to be read by 5.1 and prior: Rails.application.config.action_dispatch.use_authenticated_cookie_encryption: false

Updating Steps

Check current ruby version

  • Make sure the version of ruby meets the version specified by the version of rails

Make minor upgrades

  • If upgrading a major version of rails (ex. rails 5 to rails 6)
    • Make sure to incrementally increase the version and check the site to see where it breaks (from 5 to 5.2 to 5.x until 6.0)

Update gemfile to the version of Rails

  • gem 'rails', ~> '6.0' for example
  • In terminal, run bundle update rails
  • Fix and update gemfile dependencies
  • Update configrations by running rails app:update
  • Take a look at the new_framework_defaults.rb file to uncomment any modified settings

Upgrading from 5.2 to 6


  • Now is the default javascript compiler for rails 6, but is not automatically included: add to gemfile: gem 'webpacker'
    • then run bin/rails webpacker:install

Force SSL

  • force_ssl in controllers has been deprecated and will be removed in 6.1

Purpose and expiry metadata

  • has been moved to within signed/encrypted cookie
  • Rails.application.config.action_dispatch.use_cookies_with_metadata to false

NPM packages have been moved to within @rails scope

  • if the following packages were instgalled via npm/yarn
actioncable   → @rails/actioncable
activestorage → @rails/activestorage
rails-ujs     → @rails/ujs
  • they are now included within rails

Actioncable API has been converted to ES6 Syntax

  • If using actioncable, make the following changes:
ActionCable.WebSocket = MyWebSocket
ActionCable.adapters.WebSocket = MyWebSocket

ActionCable.logger = myLogger
ActionCable.adapters.logger = myLogger

ActionCable.logger.enabled = true

ActionCable.logger.enabled = false


  • calling .content_type now returns the charset
  • use .media_type to return just the mime type

config.hosts setting

  • allows you to add hosts when in development environment
# config/environments/development.rb
config.hosts << ""
# can also use regexp:
config.hosts << /[a-zA-Z0-9]


  • files classes, and modules are now automatically loaded using zeitwerk
    • zeitwerk autoloads or eager loads all files in your app so that no require_directive statements are needed
# config/application.rb
config.load_defaults 6.0

# if upgrdaing from older version of rails
# config/application.rb
config.autoloader :zeitwerk 

Autoload paths

  • app/models/concerns/foo.rb can now be defined as Foo and not Concerns::Foo
  • concerns folder has now been added to the autoload path (assumed as root directory, namespace has been ignored)
  • When working with an API set up, files like app/api/base.rb, usually defined as Api::Base will now be defined as just Base
    • rails adds all subdirectories of app/ to the autoload paths
    • to keep that naming convention, remove the desired path from the auto- load path:
  • Always use classes or modules when defining constants
  • One class per file, unless nested within module
  • config.cache_classes = false to turn enable reloading in the test env
  • Bootsnap should be atleast version 1.4.2
  • You can use classic mode instead of zeitwerk by:
# config/application.rb
config.load_defaults 6.0
config.autoloader = :classic

Active Storage

* `has_many_attached` used to append new files to the collection
* new behavior: overwrites the current collection
* use `attach` to add new attachments without overwriting the existing ones