Skip to content

fastruby/next_rails

 
 

Next Rails

Continuous Integration Gem Version MIT License

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.

Features

  • 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

Installation

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 install

Dual Boot

We 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.

Setup

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 s

Conditional code

When 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"
end

Or 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"
end

Both 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.

Bundle Report

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 --help

Deprecation Tracking

Track deprecation warnings in your test suite so you can monitor and fix them incrementally.

RSpec

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
end

Minitest

Add 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}/", "") }
  )
end

Note

This is currently not compatible with the minitest/parallel_fork gem.

Running deprecation tracking

# Save current deprecations to the shitlist
DEPRECATION_TRACKER=save rspec

# Fail if deprecations have changed since the last save
DEPRECATION_TRACKER=compare rspec

Parallel CI support

When 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

RSpec.configure do |config|
  if ENV["DEPRECATION_TRACKER"]
    DeprecationTracker.track_rspec(
      config,
      node_index: ENV["CI_NODE_INDEX"]
    )
  end
end

The 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.

Merging shards

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-shards

You can also merge shards programmatically:

DeprecationTracker.merge_shards(
  "spec/support/deprecation_warning.shitlist.json",
  delete_shards: true
)

Example CI workflow

# 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>

deprecations command

View, filter, and manage stored deprecation warnings:

deprecations info
deprecations info --pattern "ActiveRecord::Base"
deprecations merge --delete-shards
deprecations run
deprecations --help

CLI Reference

bundle exec next_rails --init    # Set up dual boot
bundle exec next_rails --version # Show gem version
bundle exec next_rails --help    # Show help

Contributing

Bug reports and pull requests are welcome! See the Contributing guide for setup instructions and guidelines.

Releases

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

Steps to release a new version

  1. Update the version number in lib/next_rails/version.rb
  2. Update CHANGELOG.md with the appropriate headers and entries
  3. Commit your changes to a release/v1.x.x branch
  4. Push your changes and submit a pull request Release v1.x.x
  5. Merge your pull request to the main branch
  6. Tag the latest version on main: git tag v1.x.x
  7. Push the tag to GitHub: git push --tags
  8. Build the gem: gem build next_rails.gemspec
  9. Push to RubyGems: gem push next_rails-1.x.x.gem

Maintainers

Maintained by OmbuLabs / FastRuby.io.

History

This gem started as a fork of ten_years_rails, a companion to the "Ten Years of Rails Upgrades" conference talk by Jordan Raine.

License

The gem is available as open source under the terms of the MIT License.