The Complete Guide for Deprecation Warnings in Rails

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 opens a new window 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 opens a new window to address deprecation warnings when we upgrade Rails applications opens a new window .

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 opens a new window or Travis CI opens a new window ) 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 opens a new window or Airbrake opens a new window ).

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 opens a new window 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.

Deprecation Warning Story for Rails Upgrade

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 opens a new window 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 opens a new window 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 opens a new window , you can write a cop to check for deprecated code. Take a look at Lint/DeprecatedClassMethods opens a new window 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 opens a new window 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 opens a new window

Get the book