diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 772a50b3688..dfd28c734cb 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -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`
diff --git a/activesupport/lib/active_support/core_ext/module/deprecation.rb b/activesupport/lib/active_support/core_ext/module/deprecation.rb
index 71c42eb3575..596001f1cda 100644
--- a/activesupport/lib/active_support/core_ext/module/deprecation.rb
+++ b/activesupport/lib/active_support/core_ext/module/deprecation.rb
@@ -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 deprecation_warning(deprecated_method_name, message, caller_backtrace)
- # 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 deprecation_warning(deprecated_method_name, message, caller_backtrace) 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
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index 490c048ccec..29c88f63263 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -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
diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb
index d95082efbfe..552eb132d63 100644
--- a/activesupport/lib/active_support/deprecation/behaviors.rb
+++ b/activesupport/lib/active_support/deprecation/behaviors.rb
@@ -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)
diff --git a/activesupport/lib/active_support/deprecation/constant_accessor.rb b/activesupport/lib/active_support/deprecation/constant_accessor.rb
index 1ed00158123..73e2a190e72 100644
--- a/activesupport/lib/active_support/deprecation/constant_accessor.rb
+++ b/activesupport/lib/active_support/deprecation/constant_accessor.rb
@@ -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
diff --git a/activesupport/lib/active_support/deprecation/instance_delegator.rb b/activesupport/lib/active_support/deprecation/instance_delegator.rb
index 59dd30ae303..24b8d0822d5 100644
--- a/activesupport/lib/active_support/deprecation/instance_delegator.rb
+++ b/activesupport/lib/active_support/deprecation/instance_delegator.rb
@@ -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
diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb
index 54375982c2a..921168c94ab 100644
--- a/activesupport/lib/active_support/deprecation/method_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb
@@ -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!
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
index bd236375926..d49b834d5bf 100644
--- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -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)
# # => #
#
# deprecated_object.to_s
@@ -37,10 +36,11 @@ module ActiveSupport
# (Backtrace)
# # => "#"
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
diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb
index bad80975029..657d962c601 100644
--- a/activesupport/lib/active_support/deprecation/reporting.rb
+++ b/activesupport/lib/active_support/deprecation/reporting.rb
@@ -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
- # ActiveSupport::Deprecation.behavior.
+ # Outputs a deprecation warning to the output configured by ActiveSupport::Deprecation#behavior.
#
- # 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 if: argument accepts a truthy/falsy value or an object that
# responds to .call. 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)
diff --git a/activesupport/lib/active_support/deprecator.rb b/activesupport/lib/active_support/deprecator.rb
index 6cdcbc2bcb3..3e3c38ecd23 100644
--- a/activesupport/lib/active_support/deprecator.rb
+++ b/activesupport/lib/active_support/deprecator.rb
@@ -2,6 +2,6 @@
module ActiveSupport
def self.deprecator # :nodoc:
- @deprecator ||= ActiveSupport::Deprecation.new
+ ActiveSupport::Deprecation._instance
end
end
diff --git a/activesupport/lib/active_support/testing/deprecation.rb b/activesupport/lib/active_support/testing/deprecation.rb
index 4350416286d..073300bb81f 100644
--- a/activesupport/lib/active_support/testing/deprecation.rb
+++ b/activesupport/lib/active_support/testing/deprecation.rb
@@ -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|
diff --git a/activesupport/test/deprecation/method_wrappers_test.rb b/activesupport/test/deprecation/method_wrappers_test.rb
index 65c8b50a452..2d5a44561a6 100644
--- a/activesupport/test/deprecation/method_wrappers_test.rb
+++ b/activesupport/test/deprecation/method_wrappers_test.rb
@@ -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
diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb
index f05882fdb0e..4a5d7ab2179 100644
--- a/activesupport/test/deprecation_test.rb
+++ b/activesupport/test/deprecation_test.rb
@@ -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
diff --git a/guides/Rakefile b/guides/Rakefile
index 59cbe79869c..9d684d82bb7 100644
--- a/guides/Rakefile
+++ b/guides/Rakefile
@@ -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
diff --git a/railties/lib/rails/deprecator.rb b/railties/lib/rails/deprecator.rb
index 320b00b6938..2ac56b10434 100644
--- a/railties/lib/rails/deprecator.rb
+++ b/railties/lib/rails/deprecator.rb
@@ -2,6 +2,6 @@
module Rails
def self.deprecator # :nodoc:
- ActiveSupport::Deprecation.instance
+ @deprecator ||= ActiveSupport::Deprecation.new
end
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index d9c67ac11ab..7037f678247 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -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]