Skip to main content
Test Double company logo
Services
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say Hello
Test Double logo
Menu
Services
BackGrid of dots icon
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
Cycle icon
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say hello
Developers
Developers
Developers
Rails upgrades

Adding disallowed deprecations to Rails 6.1

Discover how the Disallowed Deprecations feature in Rails 6.1 helps you maintain your app efficiently. Say goodbye to pesky deprecation warnings for good!
Cliff Pruitt
|
December 14, 2020
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Rails upgrades comprise a solid chunk of the work we do for our clients.

Upgrades may not always be the most glamorous task on the list but it can certainly be one of the most strategically valuable for long term maintenance of our apps. Because deprecations give us early warning about problems our code will have with upcoming upgrades, eliminating those deprecation warnings is an important part of the upgrade process.

Fixing the deprecations themselves can be relatively straightforward. What is often less obvious is how to deal with preventing deprecations from being re-added after they’ve been resolved. As Kerry Diehl, a fellow Test Double agent, asked not too long ago:

We’ve been working through a bunch of fixes for deprecation warnings that were previously ignored. But once they have been fixed, they are off of our radar, so to speak. Has anybody implemented anything to prevent deprecated code from being added during the process of a rails upgrade?
- Kerry Diehl

I had the opportunity to implement such a feature while we worked with GitHub to help prepare their app for Rails 6.1. We decided to share this with the Ruby community and ported the solution to Rails as ActiveSupport’s Disallowed Deprecations which is part of the new Rails 6.1 release. Before we get into what Disallowed Deprecations are, lets take a look at the problem in a bit more detail.

A problem scenario

Lets assume we’re performing a Rails upgrade on our app and are working on eliminating deprecation warnings.

After a particular class of warning is resolved we want to be able to move on to the next one. We need to prevent engineers from inadvertently re-introducing the same deprecation while we continue to make incremental progress on the upgrade. Complicating matters, our app is configured to silence deprecation warnings when running in test mode to keep CI output clean. Consequently, other developers on our team don’t even see deprecation warnings until they deliberately enable them. We want to treat these resolved deprecation warnings as hard failures in our development and test environments and want to log them in production.

Rails already has ActiveSupport::Deprecation.behavior. It provides some amount of control over how deprecation warnings are handled. Setting this value to :raise will raise exceptions on all deprecations which may be a bit overkill. Setting the value to a Proc allows you to take different actions depending on the text of the warning encountered. At first glance this seems like what we want, however the limitation here is that that the Proc will not be executed at all! If we set ActiveSupport::Deprecation.silenced = true (as we happen to do in our test environment) Rails will skip the deprecation entirely and never call the Proc. Since Rails didn’t provide an ideal solution for the problem, we wrote a small but very useful API to improve the workflow for eliminating deprecations.

Introducing disallowed deprecations

Now that GitHub is consistently running the latest version of Rails, they have become a heavy contributor to Rails and when possible generally prefer improving the framework over adding general framework features directly to their app.

While helping GitHub prepare for a Rails upgrade, I had the chance to work on a way to handle these deprecation regressions and to upstream this work as ActiveSupport’s Disallowed Deprecations which allows specific deprecation warnings to be treated as failures. By default, disallowed deprecations will raise exceptions in development and test environments and log in production.

This API consists of three parts:

  • ActiveSupport::Deprecation.disallowed_warnings allows configuration of the deprecation warnings that will no longer be allowed in the app
  • ActiveSupport::Deprecation.disallowed_behavior allows overriding the default raise/log disallowed behavior
  • ActiveSupport::Deprecation.allow allows all or some deprecations to be temporarily allowed within a passed block

ActiveSupport::Deprecation.disallowed_warnings

The .disallowed_warnings config option allows specifying which deprecation warning messages will be treated as exceptions. The value is an array which can contain strings or symbols which will be evaluated as a substring match or a regular expression to match against the message text.

# config/initializers/deprecations.rb

ActiveSupport::Deprecation.disallowed_warnings = [
  "calling bad_method is deprecated",
  :worse_method,
  /(horrible|unsafe)_method/
]

Disallowed deprecations can also be configured to the symbol :all which will raise an exception for all deprecation warnings.

ActiveSupport::Deprecation.disallowed_warnings = :all

ActiveSupport::Deprecation.disallowed_behavior

By default, the behavior for disallowed messages defaults to :raise in development and test and :log in production. Alternatively the behavior can be configured in the same way as ActiveSuppor::Deprecation.behavior=.

if Rails.env.production?
  ActiveSupport::Deprecation.disallowed_behavior = ->(message, callstack, deprecation_horizon, gem_name) {
    # custom deprecation handling ...
  }
end

ActiveSupport::Deprecation.allow

To override these settings in your app, the allow method temporarily re-allows disallowed deprecation warnings that occur within the given block!

ActiveSupport::Deprecation.allow do
  User.do_thing_that_calls_bad_and_worse_method
end

One or more specific messages can be matched to re-allow only certain deprecations:

ActiveSupport::Deprecation.allow [:bad_method, "worse_method"] do
  User.do_thing_that_calls_bad_and_worse_method
end

Other options to handle unwanted deprecation warnings

There are a few other ways of handling unwanted deprecation warnings that are worth mentioning.

First, Rails still provides ActiveSupport::Deprecation.behavior API which can be set to :notify or a Proc to allow more granular control over deprecation warnings. This requires more app code to be written and, as noted above, doesn’t work with silenced deprecations but it may be an option worth considering.

Second, the Deprecation Toolkit gem, maintained by Shopify, is another approach to wrangling deprecations. This gem is a good bit more complex than Disallowed Deprecations but may be preferable if you have more deprecation warnings than you can deal with in a single focused effort. Deprecation Toolkit first records and allows all existing deprecations, only raising exceptions if new deprecation warnings are encountered. Over time you can resolve deprecations and remove them from the allowed list. This gem also may be a good option if you need to handle deprecations that use Kernel#warn (as many gems do) instead of ActiveSupport::Deprecation#warn to output the message.

Contributing to Rails

I began dabbling with Rails somewhere around version 2 and built my first “real Rails app” with version 3.

Over the years I observed the contributions so many people made to the framework and often thought about how rewarding it would be to contribute something of my own. Quite honestly, I considered it extremely intimidating and something I lacked the ability to do. (That was best left to the “real” Rails engineers.)

Two years ago I set aside a good deal of apprehension and imposter syndrome and went through the interview process with Test Double. That decision provided the opportunity to work with GitHub on this and several other Rails PRs. More importantly it allowed me to see how much experience and ability I really had developed over the years. If you care deeply about improving the way the world writes software Test Double might be a great fit for you too. We want to hear from you.

Finally, I’m very appreciative to Eileen Uchitelle for her help and guidance on this feature.

Related Insights

🔗
Zero downtime Rails upgrades
🔗
Why it’s worth outsourcing your Rails upgrades
🔗
Managing Ruby hashes in Rails upgrades

Explore our insights

See all insights
Leadership
Leadership
Leadership
Why we coach the system, not just the team

Slow delivery isn’t usually about your people—it’s about your system. Shifting focus to incremental improvements in the system helps change not just processes but behaviors for lasting change.

by
Doc Norton
Developers
Developers
Developers
Developer QA checklist for feature releases

Quality Assurance is a mindset integrated throughout development to catch issues early, build user trust, and reduce maintenance costs. These recommended procedures for dev teams without dedicated QA roles establish collective responsibility for ensuring feature stability, functionality, and usability before release.

by
Lee Quarella
Developers
Developers
Developers
From engineer to consultant: The powerful shift from inward to outward focus

What transforms a skilled software engineer into an exceptional consultant? Approach new codebases with respect rather than judgment, embrace constraints as creative boundaries, and prioritize client needs over personal preferences.

by
Dave Mosher
Letter art spelling out NEAT

Join the conversation

Technology is a means to an end: answers to very human questions. That’s why we created a community for developers and product managers.

Explore the community
Test Double Executive Leadership Team

Learn about our team

Like what we have to say about building great software and great teams?

Get to know us
No items found.
Test Double company logo
Improving the way the world builds software.
What we do
Services OverviewSoftware DeliveryProduct ManagementLegacy ModernizationDevOpsUpgrade RailsTechnical RecruitmentTechnical Assessments
Who WE ARE
About UsCulture & CareersGreat CausesEDIOur TeamContact UsNews & AwardsN.E.A.T.
Resources
Case StudiesAll InsightsLeadership InsightsDeveloper InsightsProduct InsightsPairing & Office Hours
NEWSLETTER
Sign up hear about our latest innovations.
Your email has been added!
Oops! Something went wrong while submitting the form.
Standard Ruby badge
614.349.4279hello@testdouble.com
Privacy Policy
© 2020 Test Double. All Rights Reserved.