Warning about deprecations in Ruby

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:

  1. It’s not very well documented, so hardly anyone knows.
  2. 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] # => false
  • Warning[:experimental] # => true
  • Warning[: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.