Wanting into deprecation warnings is a vital behavior to take care of an up-to-date tech stack.
Due to the specific configuration of ActiveSupport::Deprecation
within the environment-specific configuration
recordsdata, it’s fairly widespread to deal with deprecation warnings coming from Rails.
Nonetheless, I not often see initiatives configured correctly to deal with deprecation warnings coming from Ruby itself.
As we all the time need to maintain each Rails and Ruby up-to-date, it’s essential to deal with each varieties of deprecation warnings.
How does Rails deal with its deprecation warnings?
Within the surroundings configuration recordsdata, Rails units up the ActiveSupport::Deprecation
like this:
# config/environments/improvement.rb
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Increase exceptions for disallowed deprecations.
config.active_support.disallowed_deprecation = :increase
# Inform Lively Assist which deprecation messages to disallow.
config.active_support.disallowed_deprecation_warnings = []
It merely signifies that, within the improvement surroundings, all deprecation warnings will likely be logged to the Rails logger and if
there are any deprecations we received’t settle for, an exception will likely be raised.
We often need to disallow for deprecations that we’ve got already dealt with to keep away from regressions.
Out there behaviors for config.active_support.deprecation
are: :increase
, :stderr
, :log
, :notify
, :report
, and
:silence
. It’s also possible to move any object that responds to the name
methodology, i.e. a lambda.
We often set it to :increase
or :log
within the improvement. It’s an excellent observe to gather them into an artifact on CI
within the take a look at surroundings.
# config/environments/take a look at.rb
if ENV.has_key?('CI')
logger = Logger.new('log/deprecations.txt')
config.active_support.deprecation = logger.methodology(:information)
else
config.active_support.deprecation = :log
finish
Within the manufacturing surroundings, however, we usually need to log however by no means increase.
Nonetheless, an auto-generated config/environments/manufacturing.rb
file units
config.active_support.report_deprecations = false
which is equal to :silence
behaviour.
We’d like guide intervention to start out gathering deprecation warnings from the manufacturing surroundings.
How about Ruby deprecation warnings?
Ruby also can emit deprecation warnings, but it surely’s not as easy as in Rails and requires an express setup.
It makes use of the built-in Warning
module to inform about deprecated options getting used.
Nonetheless, by default warnings issued by Ruby are printed to $stderr
, which is often ignored by builders.
Furthermore, Ruby ranging from model 2.7.2, wouldn’t concern this sure sort
of warning except we explicitly inform it to take action with Warning[:deprecated] = true
.
An strategy that I like to recommend is to use the identical technique to Ruby deprecation warnings as it’s configured for Rails.
We are able to do it by overriding the Kernel#warn
methodology, which is utilized by Ruby to print warnings and make it move sure
messages to the ActiveSupport::Deprecation#warn
methodology.
# config/initializers/capture_ruby_warnings.rb
Rails.utility.deprecators[:ruby] = ActiveSupport::Deprecation.new(nil, 'Ruby')
module CaptureRubyWarnings
def warn(message, class: nil)
if class == :deprecated
Rails.utility.deprecators[:ruby].warn("#{message}", caller)
else
tremendous
finish
finish
finish
Warning[:deprecated] = true
Warning.lengthen(CaptureRubyWarnings)
Earlier than Ruby 3, there was not a class
key phrase argument in
the Kernel#warn
methodology, so we’ve got to carry out some string matching to find out if the message is a deprecation
warning if we’re on Ruby < 3.
# config/initializers/capture_ruby_warnings.rb
Rails.utility.deprecators[:ruby] = ActiveSupport::Deprecation.new(nil, 'Ruby')
module CaptureRubyWarnings
def warn(message)
if message =~ /deprecated/i
Rails.utility.deprecators[:ruby].warn("#{message}", caller)
else
tremendous
finish
finish
finish
Warning[:deprecated] = true if Warning.respond_to?(:[]=) # Warning responds to []= since Ruby 2.7.0
Warning.lengthen(CaptureRubyWarnings)
Previous to Rails 7.1, there weren’t a set of deprecators in
utility configuration to outline one per dependency. We used to name international ActiveSupport::Deprecation
singleton
straight again then.
# config/initializers/capture_ruby_warnings.rb
module CaptureRubyWarnings
def warn(message, class: nil)
if class == :deprecated
ActiveSupport::Deprecation.warn("[RUBY] #{message}", caller)
else
tremendous
finish
finish
finish
Warning[:deprecated] = true
Warning.lengthen(CaptureRubyWarnings)
# config/initializers/capture_ruby_warnings.rb
module CaptureRubyWarnings
def warn(message)
if message =~ /deprecated/i
ActiveSupport::Deprecation.warn("[RUBY] #{message}", caller)
else
tremendous
finish
finish
finish
Warning[:deprecated] = true if Warning.respond_to?(:[]=) # Warning responds to []= since Ruby 2.7.0
Warning.lengthen(CaptureRubyWarnings)