The Complete Guide for Deprecation Warnings in Rails
Deprecation warnings are a common thing in our industry. They are warnings that notify us that a specific feature (e.g. a method) will be removed soon (usually in the next minor or major version) and should be replaced with something else. Features are deprecated rather than immediately removed, in order to provide backward compatibility (a solution that works in both the current and the future version), and to give programmers time to implement the code in a way that follows the new standard.
In this guide we’ll show you what the workflow is that we use at FastRuby.io to address deprecation warnings when we upgrade Rails applications .
Finding
There are a few different ways to find deprecation warnings in your application.
If you have good test coverage, you can run the whole test suite and look at the logs that were generated. If you are using a CI service (like CircleCI or Travis CI ) you can easily see the logs once the build finishes running. Otherwise, if you run the tests locally, you can look at the output in the console or in the log/test.log
file.
In Rails, all deprecation warnings start with DEPRECATION WARNING:
, so you can search for that string in your logs.
When it comes to production, the easiest way to discover deprecation warnings is by using a monitoring tool (like Honeybadger or Airbrake ).
This is not standard behavior, but it is quite useful. In order to send deprecation warnings to one of these tools, you would have to do something like this:
# config/environments/production.rb
config.active_support.deprecation = :notify
# config/initializers/deprecation_warnings.rb
ActiveSupport::Notifications.subscribe('deprecation.rails') do |name, start, finish, id, payload|
# Example if you use Honeybadger:
Honeybadger.notify(
error_class: "deprecation_warning",
error_message: payload[:message],
backtrace: payload[:callstack]
)
# Example if you use Sentry:
Raven.capture_message('DEPRECATION WARNING', {
extra: {
message: payload[:message],
callstack: payload[:callstack]
}
})
# Example if you use Rollbar:
Rollbar.info(payload[:message], payload[:callstack])
end
See this link for more details about ActiveSupport::Notifications.subscribe
.
You can also set config.active_support.deprecation
to :log
and look at the log/production.log
file, but it won’t be as straightforward as the first option. Depending on the traffic your application gets, your production.log
might have a lot of noise.
Tracking
Once you have all the deprecation warnings (or most of them) from your application, it is a good idea to track them as if they were issues. You can use the project management tool of your preference and create an issue in the backlog for each root cause of the deprecation warnings. That way it makes things a lot easier when it comes to code review and organization in general.
Also, it is a good idea to prioritize the deprecation warnings based on the frequency that they occur. That way, you make sure you first work on the ones that fix the largest amount of errors for the next Rails version. You will clearly see that if you are using dual booting in your app.
Fixing
At this point you can grab a story from the top of the backlog and work on it. Most of the deprecation warnings are very clear on what needs to be updated. If that’s not the case, a quick google search will provide more answers. Usually you will have to apply the same fix across many files, so make sure you search for all occurrences in the project folder.
Keep in mind that sometimes deprecation warnings can also happen inside gems. That usually happens when the gem has rails
as a dependency and uses deprecated code in it. If that’s the case you should consider upgrading that gem.
Once the changes are done, run the appropriate specs or manually test the parts that were modified to make sure that everything works normally.
After that, you can create a new pull request and move on to the next deprecation warning on your backlog.
Best Practices
In order to not accumulate deprecation warnings in your application, it is a good practice to treat them as errors.
You can easily configure that in your in your config/environments/test.rb
and config/environments/development.rb
files:
config.active_support.deprecation = :raise
Avoiding Regressions
After you fix a deprecation warning in the project, you want to make sure that nobody introduces that deprecated code again.
Rubocop
If you are using Rubocop , you can write a cop to check for deprecated code. Take a look at Lint/DeprecatedClassMethods for some references on that.
Disallowed deprecations in ActiveSupport
Rails 6.1 came with a new feature to disallow deprecations. We are able to configure the deprecation warnings that were fixed as disallowed. If a disallowed deprecation is introduced, it will be treated as a failure and raise an exception in development and test. In production it will log the deprecation as an error.
# config/environments/test.rb
ActiveSupport::Deprecation.disallowed_behavior = [:raise]
ActiveSupport::Deprecation.disallowed_warnings = [
"uniq",
:uniq,
/(uniq)!?/,
]
Check out this PR for more details about this new feature.
Conclusion
Depending on the size of your application, addressing all deprecation warnings can take quite some time. But hopefully this guide will help you to do it faster.
If you need some more guidance on upgrading your Rails application check out our free eBook: The Complete Guide to Upgrade Rails