Merge pull request #47354 from etiennebarrie/deprecate-ActiveSupport-Deprecation-usage

Deprecate ActiveSupport::Deprecation singleton usage
This commit is contained in:
Rafael Mendonça França 2023-04-06 10:20:38 -04:00 committed by GitHub
commit 2f08f9ac2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 424 additions and 120 deletions

View File

@ -1,3 +1,39 @@
* Deprecate usage of the singleton `ActiveSupport::Deprecation`.
All usage of `ActiveSupport::Deprecation` as a singleton is deprecated, the most common one being
`ActiveSupport::Deprecation.warn`. Gem authors should now create their own deprecator (`ActiveSupport::Deprecation`
object), and use it to emit deprecation warnings.
Calling any of the following without specifying a deprecator argument is also deprecated:
* Module.deprecate
* deprecate_constant
* DeprecatedObjectProxy
* DeprecatedInstanceVariableProxy
* DeprecatedConstantProxy
* deprecation-related test assertions
Use of `ActiveSupport::Deprecation.silence` and configuration methods like `behavior=`, `disallowed_behavior=`,
`disallowed_warnings=` should now be aimed at the [application's deprecators](https://api.rubyonrails.org/classes/Rails/Application.html#method-i-deprecators).
```ruby
Rails.application.deprecators.silence do
# code that emits deprecation warnings
end
```
If your gem has a Railtie or Engine, it's encouraged to add your deprecator to the application's deprecators, that
way the deprecation related configuration options will apply to it as well, e.g.
`config.active_support.report_deprecations` set to `false` in the production environment will also disable your
deprecator.
```ruby
initializer "my_gem.deprecator" do |app|
app.deprecators[:my_gem] = MyGem.deprecator
end
```
*Étienne Barrié*
* Add `Object#with` to set and restore public attributes around a block
```ruby
@ -459,6 +495,9 @@
deprecator.warn("bar") # => raise ActiveSupport::DeprecationException
```
Note that global `ActiveSupport::Deprecation` methods such as `ActiveSupport::Deprecation.warn`
and `ActiveSupport::Deprecation.disallowed_warnings` have been deprecated.
*Jonathan Hefner*
* Add italic and underline support to `ActiveSupport::LogSubscriber#color`

View File

@ -1,17 +1,12 @@
# frozen_string_literal: true
class Module
# deprecate :foo
# deprecate bar: 'message'
# deprecate :foo, :bar, baz: 'warning!', qux: 'gone!'
# deprecate :foo, deprecator: MyLib.deprecator
# deprecate :foo, bar: "warning!", deprecator: MyLib.deprecator
#
# You can also use custom deprecator instance:
#
# deprecate :foo, deprecator: MyLib::Deprecator.new
# deprecate :foo, bar: "warning!", deprecator: MyLib::Deprecator.new
#
# \Custom deprecators must respond to <tt>deprecation_warning(deprecated_method_name, message, caller_backtrace)</tt>
# method where you can implement your custom warning behavior.
# A deprecator is typically an instance of ActiveSupport::Deprecation, but you can also pass any object that responds
# to <tt>deprecation_warning(deprecated_method_name, message, caller_backtrace)</tt> where you can implement your
# custom warning behavior.
#
# class MyLib::Deprecator
# def deprecation_warning(deprecated_method_name, message, caller_backtrace = nil)
@ -19,7 +14,15 @@ class Module
# Kernel.warn message
# end
# end
def deprecate(*method_names)
ActiveSupport::Deprecation.deprecate_methods(self, *method_names)
def deprecate(*method_names, deprecator: nil, **options)
if deprecator.is_a?(ActiveSupport::Deprecation)
deprecator.deprecate_methods(self, *method_names, **options)
elsif deprecator
# we just need any instance to call deprecate_methods, but the deprecation will be emitted by deprecator
ActiveSupport.deprecator.deprecate_methods(self, *method_names, **options, deprecator: deprecator)
else
ActiveSupport.deprecator.warn("Module.deprecate without a deprecator is deprecated")
ActiveSupport::Deprecation._instance.deprecate_methods(self, *method_names, **options)
end
end
end

View File

@ -3,8 +3,33 @@
require "singleton"
module ActiveSupport
# \Deprecation specifies the API used by Rails to deprecate methods, instance
# variables, objects, and constants.
# \Deprecation specifies the API used by Rails to deprecate methods, instance variables, objects, and constants. It's
# also available for gems or applications.
#
# For a gem, use Deprecation.new to create a Deprecation object and store it in your module or class (in order for
# users to be able to configure it).
#
# module MyLibrary
# def self.deprecator
# @deprecator ||= ActiveSupport::Deprecation.new("2.0", "MyLibrary")
# end
# end
#
# For a Railtie or Engine, you may also want to add it to the application's deprecators, so that the application's
# configuration can be applied to it.
#
# module MyLibrary
# class Railtie < Rails::Railtie
# initializer "deprecator" do |app|
# app.deprecators[:my_library] = MyLibrary.deprecator
# end
# end
# end
#
# With the above initializer, configuration settings like the following will affect +MyLibrary.deprecator+:
#
# # in config/environments/test.rb
# config.active_support.deprecation = :raise
class Deprecation
# active_support.rb sets an autoload for ActiveSupport::Deprecation.
#
@ -25,7 +50,7 @@ module ActiveSupport
require "active_support/core_ext/module/deprecation"
require "concurrent/atomic/thread_local_var"
include Singleton
include Singleton # :nodoc:
include InstanceDelegator
include Behavior
include Reporting

View File

@ -88,10 +88,11 @@ module ActiveSupport
# Deprecation warnings raised by gems are not affected by this setting
# because they happen before Rails boots up.
#
# ActiveSupport::Deprecation.behavior = :stderr
# ActiveSupport::Deprecation.behavior = [:stderr, :log]
# ActiveSupport::Deprecation.behavior = MyCustomHandler
# ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
# deprecator = ActiveSupport::Deprecation.new
# deprecator.behavior = :stderr
# deprecator.behavior = [:stderr, :log]
# deprecator.behavior = MyCustomHandler
# deprecator.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
# # custom stuff
# }
#
@ -102,7 +103,7 @@ module ActiveSupport
end
# Sets the behavior for disallowed deprecations (those configured by
# ActiveSupport::Deprecation.disallowed_warnings=) to the specified
# ActiveSupport::Deprecation#disallowed_warnings=) to the specified
# value. As with +behavior=+, this can be a single value, array, or an
# object that responds to +call+.
def disallowed_behavior=(behavior)

View File

@ -6,8 +6,7 @@ module ActiveSupport
# hooking +const_missing+.
#
# It takes the names of an old (deprecated) constant and of a new constant
# (both in string form) and optionally a deprecator. The deprecator defaults
# to +ActiveSupport::Deprecator+ if none is specified.
# (both in string form) and a deprecator.
#
# The deprecated constant now returns the same object as the new one rather
# than a proxy object, so it can be used transparently in +rescue+ blocks
@ -19,7 +18,7 @@ module ActiveSupport
#
# PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
# include ActiveSupport::Deprecation::DeprecatedConstantAccessor
# deprecate_constant 'PLANETS', 'PLANETS_POST_2006'
# deprecate_constant 'PLANETS', 'PLANETS_POST_2006', deprecator: ActiveSupport::Deprecation.new
#
# PLANETS.map { |planet| planet.capitalize }
# # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
@ -40,7 +39,9 @@ module ActiveSupport
super
end
def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
def deprecate_constant(const_name, new_constant, message: nil, deprecator: nil)
ActiveSupport.deprecator.warn("DeprecatedConstantAccessor.deprecate_constant without a deprecator is deprecated") unless deprecator
deprecator ||= ActiveSupport::Deprecation._instance
class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
end

View File

@ -1,11 +1,10 @@
# frozen_string_literal: true
require "active_support/core_ext/module/delegation"
module ActiveSupport
class Deprecation
module InstanceDelegator # :nodoc:
def self.included(base)
base.singleton_class.alias_method(:_instance, :instance)
base.extend(ClassMethods)
base.singleton_class.prepend(OverrideDelegators)
base.public_class_method :new
@ -18,7 +17,30 @@ module ActiveSupport
end
def method_added(method_name)
singleton_class.delegate(method_name, to: :instance)
use_instead =
case method_name
when :silence, :behavior=, :disallowed_behavior=, :disallowed_warnings=, :silenced=, :debug=
target = "(defined?(Rails.application.deprecators) ? Rails.application.deprecators : ActiveSupport::Deprecation._instance)"
"Rails.application.deprecators.#{method_name}"
when :warn, :deprecate_methods, :gem_name, :gem_name=, :deprecation_horizon, :deprecation_horizon=
"your own Deprecation object"
else
"Rails.application.deprecators[framework].#{method_name} where framework is for example :active_record"
end
args = /[^\]]=\z/.match?(method_name) ? "arg" : "..."
target ||= "ActiveSupport::Deprecation._instance"
singleton_class.module_eval <<~RUBY, __FILE__, __LINE__ + 1
def #{method_name}(#{args})
#{target}.#{method_name}(#{args})
ensure
ActiveSupport.deprecator.warn("Calling #{method_name} on ActiveSupport::Deprecation is deprecated and will be removed from Rails (use #{use_instead} instead)")
end
RUBY
end
def instance
ActiveSupport.deprecator.warn("ActiveSupport::Deprecation.instance is deprecated (use your own Deprecation object)")
super
end
end

View File

@ -16,38 +16,21 @@ module ActiveSupport
# def eee; end
# end
#
# Using the default deprecator:
# ActiveSupport::Deprecation.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
# deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem')
#
# deprecator.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
# # => Fred
#
# Fred.new.aaa
# # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.1. (called from irb_binding at (irb):10)
# # DEPRECATION WARNING: aaa is deprecated and will be removed from MyGem next-release. (called from irb_binding at (irb):10)
# # => nil
#
# Fred.new.bbb
# # DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.1 (use zzz instead). (called from irb_binding at (irb):11)
# # DEPRECATION WARNING: bbb is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):11)
# # => nil
#
# Fred.new.ccc
# # DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.1 (use Bar#ccc instead). (called from irb_binding at (irb):12)
# # => nil
#
# Passing in a custom deprecator:
# custom_deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem')
# ActiveSupport::Deprecation.deprecate_methods(Fred, ddd: :zzz, deprecator: custom_deprecator)
# # => [:ddd]
#
# Fred.new.ddd
# DEPRECATION WARNING: ddd is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):15)
# # => nil
#
# Using a custom deprecator directly:
# custom_deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem')
# custom_deprecator.deprecate_methods(Fred, eee: :zzz)
# # => [:eee]
#
# Fred.new.eee
# DEPRECATION WARNING: eee is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):18)
# # DEPRECATION WARNING: ccc is deprecated and will be removed from MyGem next-release (use Bar#ccc instead). (called from irb_binding at (irb):12)
# # => nil
def deprecate_methods(target_module, *method_names)
options = method_names.extract_options!

View File

@ -25,11 +25,10 @@ module ActiveSupport
end
end
# DeprecatedObjectProxy transforms an object into a deprecated one. It
# takes an object, a deprecation message, and optionally a deprecator. The
# deprecator defaults to +ActiveSupport::Deprecator+ if none is specified.
# DeprecatedObjectProxy transforms an object into a deprecated one. It takes an object, a deprecation message, and
# a deprecator.
#
# deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated")
# deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated", ActiveSupport::Deprecation.new)
# # => #<Object:0x007fb9b34c34b0>
#
# deprecated_object.to_s
@ -37,10 +36,11 @@ module ActiveSupport
# (Backtrace)
# # => "#<Object:0x007fb9b34c34b0>"
class DeprecatedObjectProxy < DeprecationProxy
def initialize(object, message, deprecator = ActiveSupport::Deprecation.instance)
def initialize(object, message, deprecator = nil)
@object = object
@message = message
@deprecator = deprecator
ActiveSupport.deprecator.warn("DeprecatedObjectProxy without a deprecator is deprecated") unless deprecator
@deprecator = deprecator || ActiveSupport::Deprecation._instance
end
private
@ -53,15 +53,15 @@ module ActiveSupport
end
end
# DeprecatedInstanceVariableProxy transforms an instance variable into a
# deprecated one. It takes an instance of a class, a method on that class
# and an instance variable. It optionally takes a deprecator as the last
# argument. The deprecator defaults to +ActiveSupport::Deprecator+ if none
# is specified.
# DeprecatedInstanceVariableProxy transforms an instance variable into a deprecated one. It takes an instance of a
# class, a method on that class, an instance variable, and a deprecator as the last argument.
#
# Trying to use the deprecated instance variable will result in a deprecation warning, pointing to the method as a
# replacement.
#
# class Example
# def initialize
# @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request)
# @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, ActiveSupport::Deprecation.new)
# @_request = :special_request
# end
#
@ -86,11 +86,12 @@ module ActiveSupport
# example.request.to_s
# # => "special_request"
class DeprecatedInstanceVariableProxy < DeprecationProxy
def initialize(instance, method, var = "@#{method}", deprecator = ActiveSupport::Deprecation.instance)
def initialize(instance, method, var = "@#{method}", deprecator = nil)
@instance = instance
@method = method
@var = var
@deprecator = deprecator
ActiveSupport.deprecator.warn("DeprecatedInstanceVariableProxy without a deprecator is deprecated") unless deprecator
@deprecator = deprecator || ActiveSupport::Deprecation._instance
end
private
@ -103,18 +104,16 @@ module ActiveSupport
end
end
# DeprecatedConstantProxy transforms a constant into a deprecated one. It
# takes the full names of an old (deprecated) constant and of a new constant
# (both in string form) and optionally a deprecator. The deprecator defaults
# to +ActiveSupport::Deprecator+ if none is specified. The deprecated constant
# now returns the value of the new one.
# DeprecatedConstantProxy transforms a constant into a deprecated one. It takes the full names of an old
# (deprecated) constant and of a new constant (both in string form) and a deprecator. The deprecated constant now
# returns the value of the new one.
#
# PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
#
# # (In a later update, the original implementation of `PLANETS` has been removed.)
#
# PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
# PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006')
# PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("PLANETS", "PLANETS_POST_2006", ActiveSupport::Deprecation.new)
#
# PLANETS.map { |planet| planet.capitalize }
# # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
@ -128,12 +127,13 @@ module ActiveSupport
super
end
def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
def initialize(old_const, new_const, deprecator = nil, message: "#{old_const} is deprecated! Use #{new_const} instead.")
Kernel.require "active_support/inflector/methods"
@old_const = old_const
@new_const = new_const
@deprecator = deprecator
ActiveSupport.deprecator.warn("DeprecatedConstantProxy without a deprecator is deprecated") unless deprecator
@deprecator = deprecator || ActiveSupport::Deprecation._instance
@message = message
end

View File

@ -10,10 +10,9 @@ module ActiveSupport
# Name of gem where method is deprecated
attr_accessor :gem_name
# Outputs a deprecation warning to the output configured by
# <tt>ActiveSupport::Deprecation.behavior</tt>.
# Outputs a deprecation warning to the output configured by <tt>ActiveSupport::Deprecation#behavior</tt>.
#
# ActiveSupport::Deprecation.warn('something broke!')
# ActiveSupport::Deprecation.new.warn('something broke!')
# # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
def warn(message = nil, callstack = nil)
return if silenced
@ -30,11 +29,12 @@ module ActiveSupport
# Silence deprecation warnings within the block.
#
# ActiveSupport::Deprecation.warn('something broke!')
# deprecator = ActiveSupport::Deprecation.new
# deprecator.warn('something broke!')
# # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
#
# ActiveSupport::Deprecation.silence do
# ActiveSupport::Deprecation.warn('something broke!')
# deprecator.silence do
# deprecator.warn('something broke!')
# end
# # => nil
def silence(&block)
@ -61,27 +61,28 @@ module ActiveSupport
# 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+
# +ActiveSupport::Deprecation#disallowed_warnings+
#
# The optional <tt>if:</tt> argument accepts a truthy/falsy value or an object that
# responds to <tt>.call</tt>. If truthy, then matching warnings will be allowed.
# If falsey then the method yields to the block without allowing the warning.
#
# ActiveSupport::Deprecation.disallowed_behavior = :raise
# ActiveSupport::Deprecation.disallowed_warnings = [
# deprecator = ActiveSupport::Deprecation.new
# deprecator.disallowed_behavior = :raise
# deprecator.disallowed_warnings = [
# "something broke"
# ]
#
# ActiveSupport::Deprecation.warn('something broke!')
# deprecator.warn('something broke!')
# # => ActiveSupport::DeprecationException
#
# ActiveSupport::Deprecation.allow ['something broke'] do
# ActiveSupport::Deprecation.warn('something broke!')
# deprecator.allow ['something broke'] do
# deprecator.warn('something broke!')
# end
# # => nil
#
# ActiveSupport::Deprecation.allow ['something broke'], if: Rails.env.production? do
# ActiveSupport::Deprecation.warn('something broke!')
# deprecator.allow ['something broke'], if: Rails.env.production? do
# deprecator.warn('something broke!')
# end
# # => ActiveSupport::DeprecationException for dev/test, nil for production
def allow(allowed_warnings = :all, if: true, &block)

View File

@ -2,6 +2,6 @@
module ActiveSupport
def self.deprecator # :nodoc:
@deprecator ||= ActiveSupport::Deprecation.new
ActiveSupport::Deprecation._instance
end
end

View File

@ -7,8 +7,6 @@ module ActiveSupport
module Deprecation
##
# :call-seq:
# assert_deprecated(&block)
# assert_deprecated(match, &block)
# assert_deprecated(deprecator, &block)
# assert_deprecated(match, deprecator, &block)
#
@ -29,14 +27,12 @@ module ActiveSupport
# assert_deprecated(CustomDeprecator) do
# CustomDeprecator.warn "foo should no longer be used"
# end
#
# If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
#
# assert_deprecated do
# ActiveSupport::Deprecation.warn "foo should no longer be used"
# end
def assert_deprecated(match = nil, deprecator = nil, &block)
match, deprecator = nil, match if match.is_a?(ActiveSupport::Deprecation)
unless deprecator
ActiveSupport.deprecator.warn("assert_deprecated without a deprecator is deprecated")
deprecator = ActiveSupport::Deprecation._instance
end
result, warnings = collect_deprecations(deprecator, &block)
assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
if match
@ -52,16 +48,14 @@ module ActiveSupport
# CustomDeprecator.warn "message" # fails assertion
# end
#
# If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
#
# assert_not_deprecated do
# ActiveSupport::Deprecation.warn "message" # fails assertion
# end
#
# assert_not_deprecated do
# CustomDeprecator.warn "message" # passes assertion
# assert_not_deprecated(ActiveSupport::Deprecation.new) do
# CustomDeprecator.warn "message" # passes assertion, different deprecator
# end
def assert_not_deprecated(deprecator = nil, &block)
unless deprecator
ActiveSupport.deprecator.warn("assert_not_deprecated without a deprecator is deprecated")
deprecator = ActiveSupport::Deprecation._instance
end
result, deprecations = collect_deprecations(deprecator, &block)
assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
result
@ -72,18 +66,14 @@ module ActiveSupport
#
# collect_deprecations(CustomDeprecator) do
# CustomDeprecator.warn "message"
# :result
# end # => [:result, ["message"]]
#
# If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
#
# collect_deprecations do
# CustomDeprecator.warn "custom message"
# ActiveSupport::Deprecation.warn "message"
# ActiveSupport::Deprecation.new.warn "other message"
# :result
# end # => [:result, ["message"]]
def collect_deprecations(deprecator = nil)
deprecator ||= ActiveSupport::Deprecation
unless deprecator
ActiveSupport.deprecator.warn("collect_deprecations without a deprecator is deprecated")
deprecator = ActiveSupport::Deprecation._instance
end
old_behavior = deprecator.behavior
deprecations = []
deprecator.behavior = Proc.new do |message, callstack|

View File

@ -39,10 +39,13 @@ class MethodWrappersTest < ActiveSupport::TestCase
def test_deprecate_methods_warning_with_optional_deprecator
@deprecator = ActiveSupport::Deprecation.new("next-release", "MyGem")
ActiveSupport::Deprecation.deprecate_methods(@klass, :old_method, deprecator: @deprecator)
other_deprecator = ActiveSupport::Deprecation.new
other_deprecator.deprecate_methods(@klass, :old_method, deprecator: @deprecator)
assert_deprecated(/old_method .* MyGem next-release/, @deprecator) do
assert_equal @klass.new.new_method, @klass.new.old_method
assert_not_deprecated(other_deprecator) do
assert_equal @klass.new.new_method, @klass.new.old_method
end
end
end

View File

@ -39,12 +39,26 @@ class DeprecationTest < ActiveSupport::TestCase
end
end
test "assert_deprecated is deprecated without a deprecator" do
assert_deprecated(ActiveSupport.deprecator) do
assert_deprecated do
ActiveSupport::Deprecation._instance.warn
end
end
end
test "assert_not_deprecated" do
assert_not_deprecated(@deprecator) do
1 + 1
end
end
test "assert_not_deprecated is deprecated without a deprecator" do
assert_deprecated(ActiveSupport.deprecator) do
assert_not_deprecated { }
end
end
test "collect_deprecations returns the return value of the block and the deprecations collected" do
result = collect_deprecations(@deprecator) do
@deprecator.warn
@ -55,6 +69,12 @@ class DeprecationTest < ActiveSupport::TestCase
assert_match "DEPRECATION WARNING:", result.last.sole
end
test "collect_deprecations is deprecated without a deprecator" do
assert_deprecated(ActiveSupport.deprecator) do
collect_deprecations { }
end
end
test "Module::deprecate" do
klass = Class.new(Deprecatee)
klass.deprecate :zero, :one, :multi, deprecator: @deprecator
@ -88,11 +108,28 @@ class DeprecationTest < ActiveSupport::TestCase
end
end
test "Module::deprecate without a deprecator is deprecated" do
klass = Class.new(Deprecatee)
_, deprecations = collect_deprecations(ActiveSupport.deprecator) do
klass.deprecate :zero
end
assert_match "Module.deprecate without a deprecator is deprecated", deprecations.sole
assert_deprecated(/zero is deprecated/, ActiveSupport::Deprecation._instance) do
klass.new.zero
end
end
test "DeprecatedObjectProxy" do
deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, ":bomb:", @deprecator)
assert_deprecated(/:bomb:/, @deprecator) { deprecated_object.to_s }
end
test "DeprecatedObjectProxy without a deprecator is deprecated" do
assert_deprecated(ActiveSupport.deprecator) do
ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, ":bomb:")
end
end
test "nil behavior is ignored" do
@deprecator.behavior = nil
assert_deprecated("fubar", @deprecator) { @deprecator.warn("fubar") }
@ -265,6 +302,12 @@ class DeprecationTest < ActiveSupport::TestCase
assert_equal instance.foo_bar.inspect, fubar_inspected
end
test "DeprecatedInstanceVariableProxy without a deprecator is deprecated" do
assert_deprecated(ActiveSupport.deprecator) do
ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(Deprecatee.new, :foobar, "@fubar")
end
end
test "DeprecatedConstantProxy" do
proxy = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("FUBAR", "Undeprecated::Foo::BAR", @deprecator)
@ -292,6 +335,12 @@ class DeprecationTest < ActiveSupport::TestCase
end
end
test "DeprecatedConstantProxy without a deprecator is deprecated" do
assert_deprecated(ActiveSupport.deprecator) do
ActiveSupport::Deprecation::DeprecatedConstantProxy.new("Fuu", "Undeprecated::Foo")
end
end
test "deprecate_constant" do
legacy = Module.new { def self.name; "Legacy"; end }
legacy.include ActiveSupport::Deprecation::DeprecatedConstantAccessor
@ -315,6 +364,13 @@ class DeprecationTest < ActiveSupport::TestCase
end
end
test "deprecate_constant is deprecated without a deprecator" do
legacy = Module.new.include(ActiveSupport::Deprecation::DeprecatedConstantAccessor)
assert_deprecated("DeprecatedConstantAccessor.deprecate_constant without a deprecator is deprecated", ActiveSupport.deprecator) do
legacy.deprecate_constant "OLD", "NEW"
end
end
test "assert_deprecated raises when no deprecation warning" do
assert_raises(Minitest::Assertion) do
assert_deprecated(@deprecator) { 1 + 1 }
@ -328,8 +384,8 @@ class DeprecationTest < ActiveSupport::TestCase
end
test "assert_deprecated without match argument" do
assert_deprecated do
ActiveSupport::Deprecation.warn
assert_deprecated(@deprecator) do
@deprecator.warn
end
end
@ -703,6 +759,180 @@ class DeprecationTest < ActiveSupport::TestCase
end
end
test "warn delegator is deprecated" do
_, deprecations = collect_deprecations(ActiveSupport.deprecator) do
ActiveSupport::Deprecation.warn "foo"
end
assert_equal 2, deprecations.size
assert_match("foo", deprecations.first)
assert_match("use your own Deprecation object instead", deprecations.last)
end
test "deprecate_methods delegator is deprecated" do
assert_deprecated("use your own Deprecation object instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.deprecate_methods(Deprecatee)
end
end
test "silence delegator is deprecated" do
assert_deprecated("use Rails.application.deprecators.silence instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.silence { }
end
end
test "silence delegator is deprecated and delegates to the application's deprecators when available" do
with_rails_application_deprecators do
assert_deprecated("use Rails.application.deprecators.silence instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.silence do
assert_not_deprecated(@deprecator) do
@deprecator.warn
end
end
end
end
end
test "allow delegator is deprecated" do
assert_deprecated("use Rails.application.deprecators[framework].allow", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.allow { }
end
end
test "behavior delegators are deprecated" do
old_behavior = ActiveSupport::Deprecation._instance.behavior
assert_deprecated("use Rails.application.deprecators[framework].behavior", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.behavior
end
assert_deprecated("use Rails.application.deprecators.behavior= instead", ActiveSupport.deprecator) do
# we have to keep the same behavior for assert_deprecated to work
ActiveSupport::Deprecation.behavior = ActiveSupport.deprecator.behavior
end
ensure
ActiveSupport::Deprecation._instance.behavior = old_behavior
end
test "behavior= delegator is deprecated and delegates to the application's deprecators when available" do
with_rails_application_deprecators do
called = false
assert_deprecated("use Rails.application.deprecators.behavior= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.behavior = ->(*) { called = true }
@deprecator.warn
end
assert called
end
end
test "disallowed_behavior delegators are deprecated" do
old_behavior = ActiveSupport::Deprecation._instance.disallowed_behavior
assert_deprecated("use Rails.application.deprecators[framework].disallowed_behavior", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.disallowed_behavior
end
assert_deprecated("use Rails.application.deprecators.disallowed_behavior= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.disallowed_behavior = ->(*) { }
end
ensure
ActiveSupport::Deprecation._instance.disallowed_behavior = old_behavior
end
test "disallowed_behavior= delegators is deprecated and delegates to the application's deprecators when available" do
with_rails_application_deprecators do
called = false
assert_deprecated("use Rails.application.deprecators.disallowed_behavior= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.disallowed_behavior = ->(*) { called = true }
end
@deprecator.disallowed_warnings = :all
@deprecator.warn
assert called
end
end
test "debug delegators are deprecated" do
old_debug = ActiveSupport::Deprecation._instance.debug
assert_deprecated("use Rails.application.deprecators[framework].debug", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.debug
end
assert_deprecated("use Rails.application.deprecators.debug= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.debug = true
end
ensure
ActiveSupport::Deprecation._instance.debug = old_debug
end
test "debug= delegator is deprecated and delegates to the application's deprecators when available" do
with_rails_application_deprecators do
assert_deprecated("use Rails.application.deprecators.debug= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.debug = true
end
assert @deprecator.debug
end
end
test "silenced delegators are deprecated" do
old_silenced = ActiveSupport::Deprecation._instance.silenced
assert_deprecated("use Rails.application.deprecators[framework].silenced", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.silenced
end
assert_deprecated("use Rails.application.deprecators.silenced= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.silenced = false
end
ensure
ActiveSupport::Deprecation._instance.silenced = old_silenced
end
test "silenced= delegator is deprecated and delegates to the application's deprecators when available" do
with_rails_application_deprecators do
assert_deprecated("use Rails.application.deprecators.silenced= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.silenced = true
end
assert @deprecator.silenced
end
end
test "disallowed_warnings delegators are deprecated" do
old_disallowed_warnings = ActiveSupport::Deprecation._instance.disallowed_warnings
assert_deprecated("use Rails.application.deprecators[framework].disallowed_warnings", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.disallowed_warnings
end
assert_deprecated("use Rails.application.deprecators.disallowed_warnings= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.disallowed_warnings = []
end
ensure
ActiveSupport::Deprecation._instance.disallowed_warnings = old_disallowed_warnings
end
test "disallowed_warnings= delegator is deprecated and delegates to the application's deprecators when available" do
with_rails_application_deprecators do
assert_deprecated("use Rails.application.deprecators.disallowed_warnings= instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.disallowed_warnings = :all
end
assert_equal :all, @deprecator.disallowed_warnings
end
end
test "gem_name delegators are deprecated" do
old_gem_name = ActiveSupport::Deprecation._instance.gem_name
assert_deprecated("use your own Deprecation object instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.gem_name
end
assert_deprecated("use your own Deprecation object instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.gem_name = "MyGem"
end
ensure
ActiveSupport::Deprecation._instance.gem_name = old_gem_name
end
test "deprecation_horizon delegators are deprecated" do
old_deprecation_horizon = ActiveSupport::Deprecation._instance.deprecation_horizon
assert_deprecated("use your own Deprecation object instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.deprecation_horizon
end
assert_deprecated("use your own Deprecation object instead", ActiveSupport.deprecator) do
ActiveSupport::Deprecation.deprecation_horizon = "2.0"
end
ensure
ActiveSupport::Deprecation._instance.deprecation_horizon = old_deprecation_horizon
end
test "warn deprecation skips the internal caller locations" do
@deprecator.behavior = ->(_, callstack, *) { @callstack = callstack }
method_that_emits_deprecation(@deprecator)
@ -715,6 +945,13 @@ class DeprecationTest < ActiveSupport::TestCase
deprecator.warn
end
def with_rails_application_deprecators(&block)
application = Struct.new(:deprecators).new(ActiveSupport::Deprecation::Deprecators.new)
rails = Struct.new(:application).new(application)
rails.application.deprecators[:deprecator] = @deprecator
stub_const(Object, :Rails, rails, &block)
end
def deprecator_with_messages
klass = Class.new(ActiveSupport::Deprecation)
deprecator = klass.new

View File

@ -12,8 +12,7 @@ namespace :guides do
desc "Generate .mobi file"
task :kindle do
require "active_support/deprecation"
ActiveSupport::Deprecation.warn("The guides:generate:kindle rake task is deprecated and will be removed in 7.2. Run rake guides:generate:epub instead")
warn("DEPRECATION WARNING: The guides:generate:kindle rake task is deprecated and will be removed in 7.2. Run rake guides:generate:epub instead.")
Rake::Task["guides:generate:epub"].invoke
end

View File

@ -2,6 +2,6 @@
module Rails
def self.deprecator # :nodoc:
ActiveSupport::Deprecation.instance
@deprecator ||= ActiveSupport::Deprecation.new
end
end

View File

@ -4008,7 +4008,7 @@ module ApplicationTests
test "Rails.application.deprecators includes framework deprecators" do
app "production"
assert_includes Rails.application.deprecators.each, ActiveSupport::Deprecation.instance
assert_includes Rails.application.deprecators.each, ActiveSupport::Deprecation._instance
assert_equal ActionCable.deprecator, Rails.application.deprecators[:action_cable]
assert_equal AbstractController.deprecator, Rails.application.deprecators[:action_controller]
assert_equal ActionController.deprecator, Rails.application.deprecators[:action_controller]