модуль ActiveSupport::Deprecation::DeprecatedConstantAccessor
Открытые методы класса
# File activesupport/lib/active_support/deprecation/constant_accessor.rb, line 6
def self.included(base)
require "active_support/inflector/methods"
extension = Module.new do
def const_missing(missing_const_name)
if class_variable_defined?(:@@_deprecated_constants)
if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", caller_locations)
return ActiveSupport::Inflector.constantize(replacement[:new].to_s)
end
end
super
end
# Provides a way to rename constants with a deprecation cycle in which
# both the old and new names work, but using the old one prints a
# deprecation message.
#
# In order to rename <tt>A::B</tt> to <tt>C::D</tt>, you need to delete the
# definition of <tt>A::B</tt> and declare the deprecation in +A+:
#
# require "active_support/deprecation"
#
# module A
# include ActiveSupport::Deprecation::DeprecatedConstantAccessor
#
# deprecate_constant "B", "C::D", deprecator: ActiveSupport::Deprecation.new
# end
#
# The first argument is a constant name (no colons). It is the name of
# the constant you want to deprecate in the enclosing class or module.
#
# The second argument is the constant path of the replacement. That
# has to be a full path even if the replacement is defined in the same
# namespace as the deprecated one was.
#
# In both cases, strings and symbols are supported.
#
# The +deprecator+ keyword argument is the object that will print the
# deprecation message, an instance of ActiveSupport::Deprecation.
#
# With that in place, references to <tt>A::B</tt> still work, they
# evaluate to <tt>C::D</tt> now, and trigger a deprecation warning:
#
# DEPRECATION WARNING: A::B is deprecated! Use C::D instead.
# (called from ...)
#
# The message can be customized with the optional +message+ keyword
# argument.
#
# For this to work, a +const_missing+ hook is installed. When client
# code references the deprecated constant, the callback prints the
# message and constantizes the replacement.
#
# Caveat: If the deprecated constant name is reachable in a different
# namespace and Ruby constant lookup finds it, the hook won't be
# called and the deprecation won't work as intended. This may happen,
# for example, if an ancestor of the enclosing namespace has a
# constant with the same name. This is an unsupported edge case.
def deprecate_constant(old_constant_name, new_constant_path, deprecator:, message: nil)
class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
class_variable_get(:@@_deprecated_constants)[old_constant_name.to_s] = { new: new_constant_path, message: message, deprecator: deprecator }
end
end
base.singleton_class.prepend extension
end Открытые методы экземпляра
# File activesupport/lib/active_support/deprecation/constant_accessor.rb, line 10
def const_missing(missing_const_name)
if class_variable_defined?(:@@_deprecated_constants)
if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", caller_locations)
return ActiveSupport::Inflector.constantize(replacement[:new].to_s)
end
end
super
end # File activesupport/lib/active_support/deprecation/constant_accessor.rb, line 65
def deprecate_constant(old_constant_name, new_constant_path, deprecator:, message: nil)
class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
class_variable_get(:@@_deprecated_constants)[old_constant_name.to_s] = { new: new_constant_path, message: message, deprecator: deprecator }
end Позволяет переименовывать константы с использованием цикла устаревания, в котором работают и старое, и новое имена, но при использовании старого выводится сообщение об устаревании.
Чтобы переименовать A::B в C::D, необходимо удалить определение A::B и объявить устаревание в A:
require "active_support/deprecation" module A include ActiveSupport::Deprecation::DeprecatedConstantAccessor deprecate_constant "B", "C::D", deprecator: ActiveSupport::Deprecation.new end
Первый аргумент — имя константы (без двоеточий). Это имя константы, которую вы хотите объявить устаревшей во включающем её классе или модуле.
Второй аргумент — путь к константе-замене. Он должен быть полным, даже если замена определена в том же пространстве имён, что и объявленная устаревшей константа.
В обоих случаях поддерживаются строки и символы.
Именованный аргумент deprecator — это объект, который выводит сообщение об устаревании; он является экземпляром ActiveSupport::Deprecation.
После этого обращения к A::B продолжают работать: теперь они возвращают C::D и вызывают предупреждение об устаревании:
DEPRECATION WARNING: A::B is deprecated! Use C::D instead. (called from ...)
Сообщение можно настроить с помощью необязательного именованного аргумента message.
Для этого устанавливается перехватчик const_missing. Когда клиентский код обращается к объявленной устаревшей константе, обратный вызов выводит сообщение и разрешает путь к константе-замене.
Предупреждение: если имя объявленной устаревшей константы доступно в другом пространстве имён и поиск констант в Ruby находит её там, перехватчик не будет вызван, и устаревание не сработает должным образом. Такое может произойти, например, если в одном из предков включающего пространства имён есть константа с таким же именем. Этот пограничный случай не поддерживается.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.