Upgrading to Rails 5.2 - Notes

on under developer
4 minute read

Recently, I've upgraded a bunch of Apps to Rails 5.2, I want to share some common issues:

Normal process:

  1. I change the Rails requirement in Gemfile to the next minor version, like gem "rails", "~> 5.0.0"
  2. Now comes the bundle update rails, This will probably fail because some other Gems collide. If those Gems have version constraints in your Gemfile, relax that. Try adding more and more Gems to bundle update rails rack sass-rails etc.
    • Recently used bundle update lines from my bash_history: \ bash bundle update rails slim-rails simple_form pludoni-logging inherited_resources has_scope paper_trail mail devise coffee-rails redis jquery-rails rails-dom-testing bundle update rails rack thin refile json_on_rails omniauth jbuilder activeadmin inherited_resources mysql2 sass-rails sass mail_form acts-as-taggable-on rails-iframe-resizer arctic_admin font-awesome-rails simple_form
  3. Try to boot app, like bundle exec rails c, Fix any errors that happen then
  4. Run rails app:update. The guide will interactively compare all the files a newly generated Rails app brings, and your current app has. My tip: Try to adjust your files in a editor to match the Rails standard as closest as possible. E.g. our config/environments/development.rb looks almost the same like the generated. All custom config by us is then on the bottom of the file and can be easily moved betweem upgrades later.
  5. Try to run tests, fix deprecations
  6. Run development server and click around
  7. Push to CI \ Hint: Try to increase CI value, by making deprecations an error, and eager load on test (to remove bugs that happen by invalid files that the development system didn't catch) \ ```ruby

    config/environments/test.rb

    config.eager_load = ENV['CI'].present? config.active_support.deprecation = ENV['CI'].present? ? :raise : :stderr ```

Rails 5.0

Important: Protected Attributes is gone!

If you previously have used attr_accessible and similar, that stuff is gone.

Finding possible occurences:

ag new.\*params app | grep -v permit
ag update.\*params app | grep -v permit

Sometimes, e.g. for query models on a get request, this kind of pattern is useful:

# passing whole params
MyForm(params.permit!.to_h)

# passing only params, that might not be there on the first page load
MyForm(params[:my_form]&.permit!&.to_h)

Important: Belongs_to required by default

This will probably brake old apps. To reduce friction for future upgrades, adjust config/application.rb:

module MyApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.0
    ...


    config.active_record.belongs_to_required_by_default = false
  end
end

Some later Rails generator brings this line into a config/initializers, BUT WE FOUND THIS TO NOT WORK RELIABLE.

before_filter -> before_action

(Same with after_action)

sed -i 's/before_filter/before_action/g' `find app -type f`

Controller tests/specs - get/post must be keyword arguments

Just use this awesome Gems to convert everything:

gem install rails5-spec-converter
rails5-spec-converter

This converts 95% of the scenarios, only very custom session/cookies stuff must be checked manually.

redirect_to :back deprecated

-      redirect_to :back, alert: "whatever"
+      redirect_back fallback_location: '/', alert: "whatever"

Rails 5.1

  • image_tag does not allow nil! nil is not a valid asset source, wrap all image_tag in an if my_model.attachment.present?
  • database_cleaner is not required for browser tests anymore (Rspec: System Tests)
  • add 'listen' gem to development/test group gem "listen"

response.success? -> response.sucessful?

sed -i 's/be_success$/be_successful/g' `ag be_success$ spec -l`

Foreign Key mismatch

ActiveRecord::MismatchedForeignKey: Column `cooperation_id` on table `cooperation_data_points` does not match column `id` on `cooperations`, which has type `bigint(20)`. To resolve this issue, change the type of
the `cooperation_id` column on `cooperation_data_points` to be :bigint. (For example `t.bigint :cooperation_id`).
Original message: Mysql2::Error: Cannot add foreign key constraint: ALTER TABLE `cooperation_data_points` ADD CONSTRAINT `fk_rails_3979ee89c8`
FOREIGN KEY (`cooperation_id`)
  REFERENCES `cooperations` (`id`
  • Problem: db/schema.rb does not specify correct primary key types (integer vs. bigint)
  • Solution: Run rails db:schema:dump

Rails 5.2

Arel.sql

All order and pluck columns most be checked and any non-trivial statement must be wrapped in Arel.sql:

-   .order('length(name) asc').first
+   .order(Arel.sql('length(name) asc')).first

Find occurences of order/pluck with a string, check if there is function call or even an SQL injection :) (like order(params[:sort]))

  • ag "order\('"
  • ag 'order\("'
  • ag "pluck\('"
  • ag 'pluck\("'

Ruby 2.4+

Meanwhile, if you also upgrading Ruby, some common errors we run into:

webmock > 2, vcr > 3

undefined method `<<' for {:read_timeout=>3, :continue_timeout=>nil, :debug_output=>nil}:Hash

If you had running VCR version less than 3 and used HTTP Basic auth, you need to convert your cassettes: https://gist.github.com/glaszig/9170b1cf2186674faeead74a68606c5d

Deprecations Fixnum/Bignum -> Integer

  • Substitute your own usages of "Fixnum" with Integer.
  • Upgrade all Gems with the error