The Next Rails Gem

The Next Rails Gem

Did you know that we love using the Dual-Boot technique opens a new window for our Rails upgrades? We rely on the next_rails gem opens a new window to help us with dual-booting our Rails applications. This gem does more than just enable dual-booting; it also helps us identify outdated gems, check Rails compatibility, find the minimum compatible Ruby version for a target Rails version, and more.

Sounds interesting? Keep reading to learn more about the features of the next_rails gem.

History

The next_rails opens a new window gem is a fork of the ten_years_rails opens a new window gem that started as a companion to the “Ten Years of Rails Upgrades” opens a new window conference talk by Jordan Raine.

Features

1. Check Outdated Gems

Are you aware of how many outdated gems there are in your application? You can use the bundle_report outdated command to find out.

This command not only shows you the outdated gems in your application, but it also provides the latest version available for each gem.

Knowing this information can help you understand how outdated the gems are and how much effort you need to put into upgrading them. You can also use the percentage of outdated gems as a measure of your progress in getting up to date.

To generate the outdated gems report, use the following command:

bundle exec bundle_report outdated

mercenary 0.3.6: released Apr  8, 2016 (latest version, 0.4.0, released Jan 18, 2020)
colorize 0.8.1: released Jun 29, 2016 (latest version, 1.1.0, released Jun 23, 2023)
...

4 gems are sourced from git
156 of the 218 gems are out-of-date (72%)

2. Rails Compatibility

During an upgrade process, how can you determine if the gems you are using are compatible with the target Rails version? The compatibility report will display the gems that are not compatible with the target Rails version.

To generate this compatibility report, use the following command:

bundle exec bundle_report compatibility --rails-version=7.1

=> Incompatible with Rails 7.1 (with new versions that are compatible):
These gems will need to be upgraded before upgrading to Rails 7.1.

mercenary 0.3.6: - upgrade to 0.4.0
colorize 0.8.1 - upgrade to 1.1.0

2 gems incompatible with Rails 7.1

By default, the bundle_report compatibility command will exclude the Rails core gems from the report. But fret not, you can include them by passing the --include-rails-gems option.

At the end of the output, you will also see the total number of incompatible gems, which can be helpful for tracking the progress of resolving compatibility issues.

3. Minimum Ruby Version

If you want to know the Rails + Ruby compatibility, this gem has you covered! You just need to run the bundle_report ruby_check --rails-version=7.0.0 command and it will show you the minimum Ruby version required for the target Rails version:

bundle exec bundle_report ruby_check --rails-version=7.0.0

The required ruby version is >= 2.7.0 for matched rails version 7.0.0
bundle exec bundle_report ruby_check --rails-version=7.2

The required ruby version is >= 3.1.0 for matched rails version 7.2.0.beta3

Notice that if you don’t specify a patch and build versions, the tool will default to the latest released versions:

bundle exec bundle_report ruby_check --rails-version=6.1

The required ruby version is >= 2.5.0 for matched rails version 6.1.7.8

4. Deprecation Tracker

The deprecation tracker is one of my favorite features! There are two ways to use it: to save the deprecation warnings or to compare them.

Before getting started, make sure deprecations are not silenced. The gem supports RSpec and Minitest, make sure you configure it correctly opens a new window .

Save Deprecation Warnings

Why do you want to save the deprecation warnings? There are different reasons to do this, but the most common might be to save them from the CI pipeline so you can bulk add them to a project management system and more easily work on addressing them.

Okay, let’s run the tests and save the deprecation warnings:

DEPRECATION_TRACKER=save bundle exec rspec # For RSpec
DEPRECATION_TRACKER=save bundle exec test  # For Minitest

This will save a file with the deprecation report that looks something like this:

{
  "./spec/models/people_spec.rb": [
    "DEPRECATION WARNING: Date#to_s(:db) is deprecated. Please use Date#to_fs(:db) instead. (called from hired_date at spec/models/people.rb:10)",
  ]
}

This information is quite helpful as it shows which test file is triggering the deprecation warning and the specific line of code causing it. However, it might be challenging to read, especially if there are numerous deprecation warnings in the report. Check out the Deprecations Command section below for information on how to make it easier to read.

Compare Deprecation Warnings

This will compare the deprecation warnings between the last saved report and the current run. This way, you can determine if there are any changes in the deprecation warnings and identify which files are producing different deprecation warnings. Using this mode in the CI pipeline can help you catch unexpected deprecation warnings early.

DEPRECATION_TRACKER=compare bundle exec rspec # For RSpec
DEPRECATION_TRACKER=compare bundle exec test  # For Minitest

This is a sample output of the compare command:

DeprecationTracker::UnexpectedDeprecations:
    ⚠️  Deprecation warnings have changed!

    Code called by the following spec files is now generating different deprecation warnings:

    ./spec/models/people_spec.rb

    To check your failures locally, you can run:

    DEPRECATION_TRACKER=compare bundle exec rspec ./spec/models/people_spec.rb

    Here is a diff between what is expected and what was generated by this process:

          diff --git a/spec/support/deprecation_warning.shitlist.json b/tmp/temp-deprecation-tracker-shitlist20240716-240087-1b5f1cl
  index 08d0343825..604223083b 100644
  --- a/spec/support/deprecation_warning.shitlist.json
  +++ b/tmp/temp-deprecation-tracker-shitlist20240716-240087-1b5f1cl
  @@ -11,7 +11,6 @@
    "DEPRECATION WARNING: Date#to_s(:db) is deprecated. Please use Date#to_fs(:db) instead. (called from hired_date at spec/models/people.rb:10)",
       "DEPRECATION WARNING: Date#to_s(:db) is deprecated. Please use Date#to_fs(:db) instead. (called from hired_date at spec/models/people.rb:10)",
  -    "DEPRECATION WARNING: Hi there (called from block (2 levels) in <top (required)> at spec/models/people.rb:13)",

I manually added the Hi there deprecation warning to the code to show you what the diff looks like.

5. Deprecations Command

The deprecations command is designed to make the deprecation report easier to read and update as you fix deprecation warnings.

Read Deprecation Warnings

The bundle exec deprecations info command will read the deprecation report and display the deprecation warnings grouped by the top 10 most common warnings:

Ten most common deprecation warnings:
Occurrences: 11
DEPRECATION WARNING: Date#to_s(:db) is deprecated. Please use Date#to_fs(:db) instead. (called from hired_date at spec/models/people.rb:10)
----------
Occurrences: 7
DEPRECATION WARNING: TimeWithZone#to_s(:db) is deprecated. Please use TimeWithZone#to_fs(:db) instead. (called from foo at spec/models/account.rb:3)
----------
...

If you want to focus on a specific deprecation warning, you can use the --pattern option to filter the report accordingly:

bundle exec deprecations info --pattern "TimeWithZone"
Occurrences: 7
DEPRECATION WARNING: TimeWithZone#to_s(:db) is deprecated. Please use TimeWithZone#to_fs(:db) instead. (called from foo at spec/models/account.rb:3)

Update Deprecation Warnings

Let’s say you saved the deprecation report, running the following command:

DEPRECATION_TRACKER=save bundle exec rspec

In this case, the report will list any deprecation warnings related to Date and TimeWithZone and save them in the file. It’ll look like this:

# spec/support/deprecation_warning.shitlist.json
{
  "./spec/models/people_spec.rb": [
    "DEPRECATION WARNING: Date#to_s(:db) is deprecated. Please use Date#to_fs(:db) instead. (called from hired_date at spec/models/people.rb:10)",
  ],
  "./spec/models/account_spec.rb": [
    "DEPRECATION WARNING: TimeWithZone#to_s(:db) is deprecated. Please use TimeWithZone#to_fs(:db) instead. (called from foo at spec/models/account.rb:3)"
  ]
}

Then you fixed the TimeWithZone deprecation warnings, and now you want to update the deprecation report. You can run the following command to accomplish that:

bundle exec deprecations run --track-mode save --pattern "TimeWithZone"

This will remove the TimeWithZone deprecation warnings from the report, and the updated report will only list the remaining Date deprecation warnings:

# spec/support/deprecation_warning.shitlist.json
{
  "./spec/models/people_spec.rb": [
    "DEPRECATION WARNING: Date#to_s(:db) is deprecated. Please use Date#to_fs(:db) instead. (called from hired_date at spec/models/people.rb:10)",
  ]
}

6. Rails Upgrade

Last but not least, the most popular feature of the next_rails gem is the ability to use the next command to dual-boot your Rails application.

I’ll not go into details about how to use it because we have a lot of articles about it. In essence, you need to set it up opens a new window and configure opens a new window it. Then follow these articles opens a new window to use it efficiently in your Rails application.

Conclusion

I hope you find this gem as useful as we do! If any big feature is released I’ll update this article.

If you haven’t used it yet, I encourage you to give it a try, and share your thoughts with us. I’ll also extend an invite for you to contribute to the gem! Just check the contribution guide opens a new window .

Need help upgrading your Rails application? Would rather not take this on yourself? Talk to us! opens a new window

Happy Coding!

Get the book