A toolkit to upgrade your next Rails application. It helps you set up dual booting, track deprecation warnings, and get a compatibility report on outdated dependencies for any Rails application. Learn more.
- Dual Boot — Run your app against two sets of dependencies (e.g. Rails 7.1 and Rails 7.2) side by side
- Deprecation Tracking — Capture and compare deprecation warnings across test runs (RSpec & Minitest)
- Bundle Report — Check gem compatibility with a target Rails or Ruby version
- Ruby Check — Find the minimum Ruby version compatible with a target Rails version
Add this line to your application's Gemfile:
Warning
We recommend adding next_rails in the root of your Gemfile, not inside a group.
This ensures NextRails.next? and NextRails.current? are available everywhere in your codebase.
gem 'next_rails'Then run:
bundle installWe recommend upgrading one minor version at a time (e.g. 7.1 → 7.2, not 6.1 → 7.0). This keeps changes small and manageable.
Note
The next_rails --init command will add a next? helper method to the top of your Gemfile, which you can use to conditionally set gem versions.
# Initialize dual boot (creates Gemfile.next and Gemfile.next.lock)
next_rails --init
# Edit your Gemfile to conditionally set gem versions using `next?`
vim Gemfile
# Install dependencies for the next version
next bundle install
# Start your server using the next Gemfile
next rails sWhen your Gemfile targets two versions, you may need to branch application code as well:
if NextRails.next?
# Do things "the Rails 7.2 way"
else
# Do things "the Rails 7.1 way"
endOr use NextRails.current? for the inverse check:
if NextRails.current?
# Do things "the Rails 7.1 way"
else
# Do things "the Rails 7.2 way"
endBoth methods check your environment (e.g. ENV['BUNDLE_GEMFILE']) to determine which dependency set is active. This is useful for injecting Ruby or Rails shims.
Inspect your Gemfile and check compatibility with a target Rails or Ruby version.
# Show all out-of-date gems
bundle_report outdated
# Show all out-of-date gems in JSON format
bundle_report outdated --json
# Show gems incompatible with Rails 7.2
bundle_report compatibility --rails-version=7.2
# Show gems incompatible with Ruby 3.3
bundle_report compatibility --ruby-version=3.3
# Find minimum Ruby version compatible with Rails 7.2
bundle_report ruby_check --rails-version=7.2
# Help
bundle_report --helpTrack deprecation warnings in your test suite so you can monitor and fix them incrementally.
Add to rails_helper.rb or spec_helper.rb:
RSpec.configure do |config|
if ENV["DEPRECATION_TRACKER"]
DeprecationTracker.track_rspec(
config,
shitlist_path: "spec/support/deprecation_warning.shitlist.json",
mode: ENV["DEPRECATION_TRACKER"],
transform_message: -> (message) { message.gsub("#{Rails.root}/", "") }
)
end
endAdd near the top of test_helper.rb:
if ENV["DEPRECATION_TRACKER"]
DeprecationTracker.track_minitest(
shitlist_path: "test/support/deprecation_warning.shitlist.json",
mode: ENV["DEPRECATION_TRACKER"],
transform_message: -> (message) { message.gsub("#{Rails.root}/", "") }
)
endNote
This is currently not compatible with the minitest/parallel_fork gem.
# Save current deprecations to the shitlist
DEPRECATION_TRACKER=save rspec
# Fail if deprecations have changed since the last save
DEPRECATION_TRACKER=compare rspecWhen running tests across parallel CI nodes, each node can write to its own shard file to avoid conflicts. The tracker auto-detects the node index from common CI environment variables (CI_NODE_INDEX, CIRCLE_NODE_INDEX, BUILDKITE_PARALLEL_JOB, SEMAPHORE_JOB_INDEX, CI_NODE_INDEX for GitLab), or you can set it explicitly via the node_index option.
RSpec.configure do |config|
if ENV["DEPRECATION_TRACKER"]
DeprecationTracker.track_rspec(
config,
node_index: ENV["CI_NODE_INDEX"]
)
end
endThe node_index option is only used in save mode. When set, the tracker writes to a shard file (e.g. deprecation_warning.shitlist.node-0.json) instead of the canonical file. Compare mode does not support node_index and will raise an error if passed—compare should only run after merging shards on the final canonical shitlist.
After all parallel nodes finish saving, merge shards into the canonical file:
# Merge all shard files and remove them afterwards
deprecations merge --delete-shards
# Or use --next to merge shards for the next Rails version
deprecations merge --next --delete-shardsYou can also merge shards programmatically:
DeprecationTracker.merge_shards(
"spec/support/deprecation_warning.shitlist.json",
delete_shards: true
)# 1. Save phase — each parallel node writes its own shard
# (runs on every node)
DEPRECATION_TRACKER=save CI_NODE_INDEX=$NODE bundle exec rspec <subset>
# 2. Merge phase — fan-in step, runs once after all nodes finish
deprecations merge --delete-shards
# 3. Compare phase — each parallel node checks only its own buckets
# against the merged canonical file (no CI_NODE_INDEX needed)
DEPRECATION_TRACKER=compare bundle exec rspec <subset>View, filter, and manage stored deprecation warnings:
deprecations info
deprecations info --pattern "ActiveRecord::Base"
deprecations merge --delete-shards
deprecations run
deprecations --helpbundle exec next_rails --init # Set up dual boot
bundle exec next_rails --version # Show gem version
bundle exec next_rails --help # Show helpBug reports and pull requests are welcome! See the Contributing guide for setup instructions and guidelines.
next_rails follows Semantic Versioning. Given a version number MAJOR.MINOR.PATCH, we increment the:
- MAJOR version for incompatible API changes
- MINOR version for backwards-compatible new functionality
- PATCH version for backwards-compatible bug fixes
- Update the version number in
lib/next_rails/version.rb - Update
CHANGELOG.mdwith the appropriate headers and entries - Commit your changes to a
release/v1.x.xbranch - Push your changes and submit a pull request
Release v1.x.x - Merge your pull request to the
mainbranch - Tag the latest version on
main:git tag v1.x.x - Push the tag to GitHub:
git push --tags - Build the gem:
gem build next_rails.gemspec - Push to RubyGems:
gem push next_rails-1.x.x.gem
Maintained by OmbuLabs / FastRuby.io.
This gem started as a fork of ten_years_rails, a companion to the "Ten Years of Rails Upgrades" conference talk by Jordan Raine.
The gem is available as open source under the terms of the MIT License.