[Ruby on Rails (RoR)] Use ActiveSupport::Deprecation for deprecation messages in Rails

ActiveSupport::Deprecation

When upgrading a Rails application to a newer version of the framework, you’ll often see deprecation warnings pop up in your application logs and test suite output. Deprecation warnings give you time to fix an issue before it becomes an outright error. Good deprecation warnings also give you a hint on where and how to address them.

Rails makes it pretty simple to add good deprecation warnings to your actual application code, too. Let’s first look at how to do this, then talk for a moment about when it might be a good idea.

Usages

Adding the deprecation

Inside the method you want to deprecate, use ActiveSupport::Deprecation.warn, with a string to describe what’s been deprecated, and how developers should work around the deprecation going forward.

1
2
3
4
5
6
7
def process_widget
ActiveSupport::Deprecation.warn(
"#process_widget is deprecated. " \
"Use #send_widget_to_processor instead."
)
# other code ...
end

Then, in your application logs (or even better, your test suite’s output), you’ll see:

1
2
3
DEPRECATION WARNING: #process_widget is deprecated. Use
#send_widget_to_processor instead. (called from create at /path/to/
my_app/app/controllers/widgets_controller.rb:55)

Instance Public methods

Allow previously disallowed deprecation warnings within the block. allowed_warnings can be an array containing strings, symbols, or regular expressions. (Symbols are treated as strings). These are compared against the text of deprecation warning messages generated within the block. Matching warnings will be exempt from the rules set by ActiveSupport::Deprecation.disallowed_warnings

The optional if: argument accepts a truthy/falsy value or an object that responds to .call. If truthy, then matching warnings will be allowed. If falsey then the method yields to the block without allowing the warning.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ActiveSupport::Deprecation.disallowed_behavior = :raise
ActiveSupport::Deprecation.disallowed_warnings = [
"something broke"
]

ActiveSupport::Deprecation.warn('something broke!')
# => ActiveSupport::DeprecationException

ActiveSupport::Deprecation.allow ['something broke'] do
ActiveSupport::Deprecation.warn('something broke!')
end
# => nil

ActiveSupport::Deprecation.allow ['something broke'], if: Rails.env.production? do
ActiveSupport::Deprecation.warn('something broke!')
end
# => ActiveSupport::DeprecationException for dev/test, nil for production

silence(&block)

Silence deprecation warnings within the block.

1
2
3
4
5
6
7
ActiveSupport::Deprecation.warn('something broke!')
# => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"

ActiveSupport::Deprecation.silence do
ActiveSupport::Deprecation.warn('something broke!')
end
# => nil

silenced()

1
2
ActiveSupport::Deprecation.silenced
# => false

warn(message = nil, callstack = nil)

Outputs a deprecation warning to the output configured by ActiveSupport::Deprecation.behavior.

1
2
ActiveSupport::Deprecation.warn('something broke!')
# => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"

behavior=(behavior)

Sets the behavior to the specified value. Can be a single value, array, or an object that responds to call.

Available behaviors:

  • raise

    Raise ActiveSupport::DeprecationException.

  • stderr

    Log all deprecation warnings to $stderr.

  • log

    Log all deprecation warnings to Rails.logger.

  • notify

    Use ActiveSupport::Notifications to notify deprecation.rails.

  • silence

Do nothing.

Setting behaviors only affects deprecations that happen after boot time. Deprecation warnings raised by gems are not affected by this setting because they happen before Rails boots up.

1
2
3
4
5
6
ActiveSupport::Deprecation.behavior = :stderr
ActiveSupport::Deprecation.behavior = [:stderr, :log]
ActiveSupport::Deprecation.behavior = MyCustomHandler
ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
# custom stuff
}

References

[1] ActiveSupport::Deprecation::Reporting - https://api.rubyonrails.org/classes/ActiveSupport/Deprecation/Reporting.html

[2] ActiveSupport::Deprecation::Behavior - https://api.rubyonrails.org/classes/ActiveSupport/Deprecation/Behavior.html

[3] Use Active Support in Rails for deprecation messages - Andy Croll - https://andycroll.com/ruby/use-a-deprecation-message/

[4] Deprecating code in a Rails application | Everyday Rails - https://everydayrails.com/2021/07/31/rails-custom-deprecation-warnings.html