How To Delay A Rails Upgrade
Maintaining an up-to-date Ruby on Rails application is crucial for performance, security, and feature enhancements. However, finding the time for a full-scale upgrade can be challenging. In this blog post, we’ll explore practical steps you can take to delay a Rails upgrade when you don’t have the immediate bandwidth but want to set the stage for a seamless process in the future.
Before embarking on technical preparations, it’s crucial to understand why it’s important to upgrade in the first place. Besides needing to upgrade due to compliance issues and security patches, new Rails releases often bring performance optimizations and new features.
While we can’t always use the new, shiny features of new Rails versions, it is possible to become compliant through the use of services such as Rails LTS . I will explain this more in the ‘Document and Reduce Customizations’ section below.
Evaluate the Current State
Now that we know why it’s important to (eventually) upgrade, you might be wondering how to delay the process. The first step is to analyze the ecosystem around your application. Make note of your Rails version and document all your gem dependencies along with their versions.
Additionally, check for any outdated gems to identify potential areas that might require attention during an upgrade. While there’s bundle outdated
, we also have a tool in our next_rails
gem that we created to help developers extract more useful information about their gem dependencies. Add gem next_rails
to your application’s Gemfile
and run the bundle_report
command:
# Show all out-of-date gems
bundle_report outdated
bundle_report outdated
combined with libyear , a new tool that measures the age of your dependencies, can help guide you to determine what gems to prioritize. We wrote a guide to show you how you can use both gems together.
Document and Reduce Customizations Where Applicable
Next, document any customizations or patches for your Rails application. This includes modifications to models, controllers, views, and any third-party libraries. Revisit the reason why these customizations exist, and if it aligns with your goals, move to services that maintain these customizations for you.
One example is security patches. The Rails LTS service applies security patches to End of Life versions of Rails. All you have to do is pay for their service and change your Gemfile
to use their sources for the Rails gems. The downside is that yes, you have to pay for their service and that you are beholden to their whims. But you will have to weigh the upsides and downsides with your risk management.
Alternatively, you can backport patches from Rails to get the features you care about.
Update Dependencies Gradually
Next, stay proactive by updating individual dependencies regularly. At FastRuby.io, we update gems to the first minor version that contains support for the next Rails version. You can use bundler to update gems to their latest compatible versions:
# Update a specific gem
bundle update gem_name
It’s best to have a conservative approach when upgrading gems. It’s easy to think you’re upgrading one gem and then find that you’re automatically upgrading many dependencies of that gem. Always check your Gemfile.lock
and ensure you are making the least amount of changes to it as possible. We have a guide to help you update gems in a safe way .
You can use bundle_report
that comes from the next_rails
gem I mentioned in the ‘Evaluate the Current State’ section to help you find incompatible gems:
# Show gems that don't work with Rails 5.2.0
bundle_report compatibility --rails-version=5.2.0
Alternatively, you can automate this process using a tool like Dependabot , which can create pull requests for updated dependencies. If you go this route, make sure to check your pull requests to ensure that Dependabot does not make more changes to your Gemfile.lock
than needed.
Run Tests and Refactor Code
It is always important to prioritize testing. But it’s especially important when you are planning to delay upgrading - less technical debt helps keep everything running smoothly. Run your test suite regularly to catch regressions early. Take the opportunity to refactor legacy code and address technical debt. Utilize tools like RuboCop for code linting and maintain a clean, standardized codebase.
At FastRuby.io, we use three tools to help us understand a codebase’s amount of technical debt:
- Rubycritic gives the number of files that have high churn and high complexity
- Simplecov shows how well code is covered by the test suite
- Skunk shows how many files have high churn, high complexity, and low test coverage
Stay Informed About Changes
Lastly, stay informed about changes to your current Rails version. Subscribe to the Ruby on Rails mailing list, read the official release notes, and monitor Rails GitHub repositories for updates.
One major thing to focus on is addressing the deprecation warnings in your current version. There are several ways you can gather these deprecation warnings. If you use a continuous integration system and automated tests, you can use the logs resulting from your test runs to create your list. Otherwise, you can either look at your logs in development or configure a monitoring tool such as Honeybadger, Airbrake, etc. in production to notify you of deprecation warnings.
For more details on your options, take a look at our The Complete Guide for Deprecation Warnings in Rails .
Conclusion
Incorporating these steps into your development process will help you to delay the Rails upgrade while simultaneously ensuring the upgrade will go smoothly when the time is right. Remember, technical readiness today is an investment in the future stability and efficiency of your application.
Interested in paying off 1% of your tech debt every month? Let’s talk!