I’ve been looking into ways how libraries and rails engines communicate deprecation warnings and found couple of surprising things.
Everyone working with Rails probably heard or seen ActiveSupport::Deprecation in action. But what about gems that don’t depend on any rails dependencies? Kernel.warn might surprise you here.
ActiveSupport::Deprecation
Rails offers a no thrills way to emit deprecation warnings, that everyone already knows about.
Before Rails 7.1 it would look like this:
ActiveSupport::Deprecation.warn("Method will be removed in next version")
# or
deprecator = ActiveSupport::Deprecation.new("2.0", "MyGem")
deprecator.warn("Method will be removed in next version")
But starting with Rails 7.1 explicit deprecators registry became a thing. So things became even simpler.
Rails.deprecator.warn("Method will be removed in next version")
# or for specific gems
Rails.deprecators[:my_gem].warn("Method will be removed in next version")
How these deprecations are communicated can be configured with config.active_support.deprecation setting .
| Value | Result |
|---|---|
| :raise | Raise ActiveSupport::DeprecationException |
| :stderr | Logs all deprecation warnings to $stderr |
| :log | Logs all deprecation warnings to Rails.logger |
| :notify | Use ActiveSupport::Notifications to notify deprecation.rails |
| :report | Use ActiveSupport::ErrorReporter to report deprecations |
| :silence | Do nothing |
There is also a way to include stack trace with every warning if you enable debug mode.
Rails.application.deprecators.debug = true
Everything seems pretty clear and simple here. But what if you don’t depend on active support?
Kernel.warn
Turns out, that Kernel.warn is not just a generic method to emit warnings. Kernel.warn doubles down as a way to communicate deprecation’s, experimental features or performance improvements.
There are two downsides though:
- It’s not very well documented, so hardly anyone knows.
- Deprecation warnings are silenced by default
But here is way to emit a deprecation warning:
warn("Method is deprecated", category: :deprecated)
Problem is that nobody is likely to be listening. Since default values for each category are as follows:
Warning[:deprecated] # => falseWarning[:experimental] # => trueWarning[:performance] # => false
Warning and performance categories are silenced by default. But off course this could be changed by setting Warning[:deprecated] = true or using -W argument in RUBYOPTS.
export RUBYOPT="-W1:deprecated"
Or you can ask ruby to be more verbose and this will enable all warning categories:
export RUBYOPTS="-W2"
I’m hunting for deprecation’s, but performance improvement warnings can give a lot of nice hints and are worth exploring too.