Upgrading Rails 5.2 to 6
Upgrading from Rails 5.2 to 6 can bring your application new features, improvements, and security benefits. It's worth considering, but following a carefully planned approach to avoid disruptions is crucial.
Why you should upgrade to Rails 6
Whether or not you should upgrade to Rails 6 depends on several factors specific to your application and context. There are definitely benefits to consider.
-
Enhanced Developer Experience:
-
Action Text: Simplified handling of rich text content eliminates the need for custom solutions. With Trix editor, you can easily format text, add links, include quotes, create lists, and embed images and galleries.
-
Action Mailbox: Streamlined email handling, making email interactions easier to manage.
-
Testing Improvements: Parallel testing speeds up the process, and deprecation warnings guide migration more easily.
-
Hot Reloading: Code changes reflect immediately without server restarts, boosting your development workflow.
-
Multiple databases:
Using multiple databases in Rails 6 can offer many benefits, like improved performance, better data isolation, and increased flexibility.
-
-
Improved Security:
-
Host Authorization Middleware: The
ActionDispatch::HostAuthorization
is a new middleware that prevents DNS rebinding and other Host header attacks. It is included in the development environment by default. -
Security Patches: The latest updates address existing vulnerabilities and provide ongoing protection against new threats.
-
-
Performance Optimizations:
-
Turbo Drive: Faster page loading through server-side rendering and partial updates.
-
Webpacker Updates: Webpacker is the default JavaScript compiler for Rails 6. It replaces the asset pipeline.
-
-
Easy future Rails upgrade:
Investing in upgrades now builds a more maintainable codebase, benefiting you and future contributors.
How to prepare your application for Rails 6
-
Ensure you're using Ruby version 2.5 or higher. Upgrading Ruby incrementally through minor versions is recommended.
-
Before starting, back up your entire application and database thoroughly. This step is optional for most of the Rails application, but if you plan to use multiple database features, it is highly recommended to back up your databases.
-
Aim for at least 80% test coverage to catch regressions during the upgrade.
-
Have dedicated staging and testing environments for testing and deployment. Make sure to test the Rails 6 branch on staging, testing and production-like environments before making it live to actual production.
Rails 6 upgrade steps
1. Update Ruby version
Rails 6 requires Ruby 2.5 or higher. Implement a continuous integration/continuous deployment (CI/CD) pipeline for automated, incremental updates, starting with minor releases. Integrate automated website health checks into your pipeline to verify functionality after each Ruby update. The Ruby Releases provides the history of all the versions, where you can explore the release notes and identify what can go wrong with your upgrade process.
2. Update Rails to 5.2.3 (or the latest of the 5.2 series)
As a preparatory step before implementing Rails 6, it is recommended to first upgrade to version 5.2.3 and verify that all functionalities operate as intended. For projects already utilizing version 5.2, this can be accomplished with minimal effort. This initial upgrade process, although requiring additional time, ultimately served as a valuable step in preparing for the subsequent migration to Rails 6.
3. Update Gemfile Rails version to 6
You need to start by updating the Rails version in your Gemfile.
gem "rails", "~> 6.0"
Once done, execute the below command:
bundle update rails
The command updates the Rails gem in your application to the latest compatible version
within the constraints defined in your Gemfile
.
4. Fix Gemfile dependencies
If your application is young
and
has a few gems then bundle update rails
will run without any errors.
But if you have a mature application,
the bundle update rails
command will throw a list of unresolved dependencies.
Prepare for a barrage of Bundler could not find compatible versions for gem ....
errors,
but typically,
only a handful pinpoint a conflicting gem.
In one of my projects,
I faced the issue with bundle update rails
as below:
Bundler could not find compatible versions for gem "activesupport":
In Gemfile:
delayed_job (>= 3.0, < 5) was resolved to 4.1.7, which depends on
activesupport (>= 3.0, < 5.3)
rspec-rails (~> 3.5) was resolved to 3.8.2, which depends on
activesupport (>= 3.0)
jbuilder (~> 2.5) was resolved to 2.9.1, which depends on
activesupport (>= 4.2.0)
rails (~> 6.0) was resolved to 6.0.0, which depends on
activesupport (= 6.0.0)
The list was huge,
but on close observation,
we noticed the issue was with the delayed_job
gem version.
It is dependent on activesupport
6.0.
To fix this,
we had to verify which version of delayed_job
is compatible with activesupport 6.0.
Based on the gem releases,
4.1.4 is compatible with Rails 6.
The version was changed to 4.1.4,
and
the bundle update rails
command was executed
and
passed without raising any errors.
$ bundle update rails
Fetching gem metadata from https://rubygems.org/..........
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies........
Using rake 12.3.3
...
...
Bundle updated!
For huge Rails applications, you can face issues with multiple gem compatibility. You must repeat the same steps above until all the dependencies are resolved.
5. Dealing with forked gems
While working with one client,
we had a forked branch of the acts-as-taggable-on
gem.
A patch was added to the forked branch to fix one issue the client was facing.
On upgrading the client's Rails version to 6.0,
the specs started failing for the models where the gem was consumed.
On close observation,
we found the forked gem needed to be updated with the upstream acts-as-taggable-on
gem.
The upstream branch changes were pulled into the forked acts-as-taggable-on
branch.
The patch was applied,
and
the specs passed.
The changes were tested on local
and
staging environments.
6. Run rails app:update
The rails app:update
command guides you through
adding new configuration settings for Rails 6.
Be cautious
and
review each change before accepting it.
The command sequentially presents files for potential updates. For each file, you have the below choices:
-
Y
: Overwrite existing file with new default content. -
n
: Keep existing file as is. -
d
: Display differences between existing and new content. -
h
: View help for available commands. -
q
: Quit the update process.
An example output is as shown below:
exist config/application.rb
Overwrite /path/to/project/config/application.rb? (enter "h" for help) [Ynaqdh] y
force config/application.rb
create config/initializers/new_framework_defaults_6_0.rb
7. Uncomment defaults in new_framework_defaults_6_0.rb
The new_framework_defaults_6_0.rb
file is specifically created during a
Rails upgrade to version 6.0.
It contains new default configuration options introduced in that version.
The options are initially commented out,
allowing for gradual adoption
and
change control.
The new_framework_defaults_6_0.rb
file is located under the
config/initializers
directory.
You need to examine each commented-out line
and
its potential impact carefully.
To activate a default,
remove the #
symbol at the beginning of the line.
The framework file might look as below:
# new_framework_defaults_6_0.rb
# Enable the same cache key to be reused when the object being cached of type
# `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count)
# of the relation's cache key into the cache version to support recycling cache key.
# Rails.application.config.active_record.collection_cache_versioning = true
To activate collection_cache_versioning
,
you must remove the #
symbol at the beginning of the line.
Activating defaults often align your application with modern Rails conventions and best practices. But test the application thoroughly, as uncommenting can introduce changes in how your application functions.
8. Remove deprecations or warnings and fix specs
While running your application or specs, you might come across deprecation warnings. Deprecations serve as helpful warnings for potential issues arising from outdated practices or functionalities. While still functional in Rails 6, these features are slated for removal in future versions and should be addressed to ensure smooth future upgrades.
It is highly recommended to fix these warnings,
but if you want to hide them,
you can silence them by setting ActiveSupport::Deprecation.silenced
to true
.
If your application has a healthy code coverage, there might be a lot of specs that are failing. Fix these failing issues before releasing the Rails 6 version to production. The failing specs indicate what is wrong with the current code and how the upgrade has affected the code functionality.
9. Check Rails 6 release notes
You might have already gone over this step before upgrading to Rails 6; it's always good to thoroughly review the release notes. If you see any issues not addressed in your application, fix them.
10. Testing your application
Even if your application has a healthy test coverage, manual testing is required to ensure you get all crucial flow.
You need to test the application locally, and if everything looks fine, you can push the code to verify on the staging server. A few testing rounds on the staging server might help you catch potential issues that didn't appear in the development environment.
11. Release Rails 6 to production
Once your team is confident about the Rails 6 upgrade, push the changes to production and keep a watch on errors that might show up. Take your time, test thoroughly, and be prepared to backtrack if needed. Upgrading successfully will bring the benefits of Rails 6 to your application while ensuring its continued stability and security.
If you're considering a Rails 6 upgrade, learn from our journey! Check out our resources, ask us questions, and let's collectively push the boundaries of what's possible.