Warning Signs ⚠️⚠️
The Warning Signs gem builds upon the ideas of the Ruby Warning Gem and Stop ignoring your Rails (and Ruby) deprecations!.
The idea is to provide an easily-configurable way to manage deprecation warnings from Ruby and Rails to support your upgrades.
Installing Warning Signs
To install Warning Signs add
gem "warning_signs"
to your gemfile, you will most likely want it to be in all environments, but under some use cases, you may not need it in production.
Using Warning Signs
The Warning Signs gem looks for a .warning_signs.yml file when the Rails
application starts. If it does not find the file, it will not load and the
processing of deprecations will be unaffected.
You should remove any environment settings in Rails that are managing
config.active_support.deprecation, or at least those that are not
set to :notify -- use WarningSigns to handle those settings...
Handlers
Warning Signs allows you to define handlers in the YAML file. A handler consists of the following:
- Patterns to match, which can be specified with
onlyto match the patterns specified and no others, or withexceptto match all patterns except the given ones. If no patterns are specified, all patterns match. - A source, either
rubyfor deprecations triggered with Ruby'sWarnmodule, orrailsfor deprecations triggered with Rails'ActiveSupport::Deprecation. If a source is not specified, the handler matches both sources. - Environments and behaviors. An environment is either the name of a Rails
environment, the special word
allwhich matches all environments, or the special wordother, which matches any environment not specifically
invoked. - Each environment can specify one or more behaviors:
logsends a message to the Rails loggerstderrsends a message to the standard error streamraiseraises an exceptionignoredoes nothing
Handlers are matched in order. If no handler applies to a deprecation warning, Ruby warnings is ignored, Rails warnings are passed through the ActiveSupport notification mechanism.
The following example logs all deprecation warnings:
handlers:
- environment: all
behavior: log
Environments
Multiple environments need to be handled in a nested list. This example raises exceptions in the test environment, but logs in other environments
handlers:
- environments:
- environment: test
behavior: raise
- environment: other
behavior: log
Sources
This example raises exceptions for Ruby deprecations, but ignores Rails deprecations:
handlers:
- source: ruby
environment: all
behavior: raise
- source: rails
environment: all
behavior: ignore
A single environment can have multiple behaviors. This is helpful if you are, say dealing with end-to-end specs that swallow exceptions:
handlers:
- environment: all
behaviors:
- raise
- log
No matter what order you have the behaviors in, a raise behavior will be
executed last so that the other behaviors happen before the exception is
invoked.
Message Formatters
Message formatters can affect how and what data is passed to the output channel. You can define one handler:
handlers:
- environment: all
behavior: log
message_formatter:
backtrace_lines: 3
format: hash
filter_backtrace: filter_internals
There are a few attributes of message formatter that you can set
backtrace_linesis the number of filtered lines of backtrace, after the current line, that are sent to the output. The default is zero. (For raising exceptions, the default is the entire backtrace).formatcan betext,json,hash, oryaml. Non text formats are hashes with keysmessageandbacktrace, with thejsonandyamlformats converted to strings in those formats.filter_backtracehas three settings. The default isyes, which filters out Ruby internals, references to warning signs itself, and lines from gems. To not filter at all, sayno. To filter internals but not gems, sayfilter_internals.
If a message formatter is not specified, the default is a hash with zero backtrace lines.
Or you can define multiple message formatters. These can separate format based on output behavior.
In this example, log behaviors are sent in hash format, while stderr
behaviors are sent in text format. Instead of an only list, an except
list can be specified.
handlers:
- environment: all
behaviors:
- log
- stderr
- raise
message_formatters:
- backtrace_lines: 3
format: hash
behaviors:
only:
- log
- backtrace_lines: 3
format: text
behaviors:
only:
- stderr
You can also define multiple message formatters based on environment.
In this case, logs in production get hash format, while logs in development get yaml format.
handlers:
- environment: all
behaviors:
- log
message_formatters:
- backtrace_lines: 3
format: hash
environments:
only:
- production
- backtrace_lines: 3
format: yaml
environments:
only:
- development
Environments can also be listed negatively with except.
Environment and behavior matching can be used together.
If no message formatter matches a given message, the default is text format with no backtrace lines.
Pattern Matching
A common pattern is to focus only on specific deprecations and ignore others. For example, this setting file would raise on Ruby keyword argument deprecations and ignore other ruby deprecations
handlers:
- source: ruby
only:
- "Using the last argument as keyword parameters is deprecated"
- "Passing the keyword argument as the last hash parameter is deprecated"
- "Splitting the last argument into positional and keyword parameters is deprecated"
environment: all
behavior: log
Patterns are matched if the deprecation message contains the pattern as a substring.
The pattern can be a regular expression, denoted by using regular expression syntax inside the string in the YAML:
handlers:
- source: ruby
only:
- "/Using .* argument/"
environment: all
behavior: log
The pattern inside the slashes is converted to a Ruby Regexp and patterns
are matched if the regexp and the deprecation warning message match.
Another pattern is to have a list of ignored deprecations and then remove messages one by one and manage them individually.
In this case, the except pattern is used to excuse those known patterns
from the list. Other patterns will raise in test, or log in other environments.
handlers:
- source: rails
except:
- "Class level methods will no longer inherit scoping from `create!` in"
- "Uniqueness validator will no longer enforce case sensitive comparison"
- "app/models/user.rb"
environments:
- environment: test
behavior: raise
- environment: other
behavior: log
Ruby Warning Types
Ruby warnings can have an optional category, there are two predefined
categories, deprecated and experimental. You can specify a handler to
match those categories based on an "only" or "except" matcher. If you want
to specially handle warnings that do not have a defined category, you can
refer to them as blank.
This handler only handles Ruby warnings that are deprecated, other warnings are ignored.
handlers:
- environment: all
ruby_warnings:
only:
- deprecated
behavior: log
This handler handles any Ruby warning with a category
handlers:
- environment: all
ruby_warnings:
except:
- blank
behavior: log