2
2
3
3
module ActiveSupport
4
4
class Deprecation
5
- # DeprecatedConstantAccessor transforms a constant into a deprecated one by
6
- # hooking +const_missing+.
7
- #
8
- # It takes the names of an old (deprecated) constant and of a new constant
9
- # (both in string form) and a deprecator.
10
- #
11
- # The deprecated constant now returns the same object as the new one rather
12
- # than a proxy object, so it can be used transparently in +rescue+ blocks
13
- # etc.
14
- #
15
- # PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
16
- #
17
- # # (In a later update, the original implementation of `PLANETS` has been removed.)
18
- #
19
- # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
20
- # include ActiveSupport::Deprecation::DeprecatedConstantAccessor
21
- # deprecate_constant 'PLANETS', 'PLANETS_POST_2006', deprecator: ActiveSupport::Deprecation.new
22
- #
23
- # PLANETS.map { |planet| planet.capitalize }
24
- # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
25
- # (Backtrace information…)
26
- # ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
27
5
module DeprecatedConstantAccessor
28
6
def self . included ( base )
29
7
require "active_support/inflector/methods"
@@ -39,9 +17,53 @@ def const_missing(missing_const_name)
39
17
super
40
18
end
41
19
42
- def deprecate_constant ( const_name , new_constant , deprecator :, message : nil )
20
+ # Provides a way to rename constants with a deprecation cycle in which
21
+ # both the old and new names work, but using the old one prints a
22
+ # deprecation message.
23
+ #
24
+ # In order to rename <tt>A::B</tt> to <tt>C::D</tt>, you need to delete the
25
+ # definition of <tt>A::B</tt> and declare the deprecation in +A+:
26
+ #
27
+ # require "active_support/deprecation"
28
+ #
29
+ # module A
30
+ # include ActiveSupport::Deprecation::DeprecatedConstantAccessor
31
+ #
32
+ # deprecate_constant "B", "C::D", deprecator: ActiveSupport::Deprecation.new
33
+ # end
34
+ #
35
+ # The first argument is a constant name (no colons). It is the name of
36
+ # the constant you want to deprecate in the enclosing class or module.
37
+ #
38
+ # The second argument is the constant path of the replacement. That
39
+ # has to be a full path even if the replacement is defined in the same
40
+ # namespace as the deprecated one was.
41
+ #
42
+ # In both cases, strings and symbols are supported.
43
+ #
44
+ # The +deprecator+ keyword argument is the object that will print the
45
+ # deprecation message, an instance of ActiveSupport::Deprecation.
46
+ #
47
+ # With that in place, client code referencing <tt>A::B</tt> will see
48
+ #
49
+ # DEPRECATION WARNING: A::B is deprecated! Use C::D instead.
50
+ # (called from ...)
51
+ #
52
+ # The message can be customized with the optional +message+ keyword
53
+ # argument.
54
+ #
55
+ # For this to work, a +const_missing+ hook is installed. When client
56
+ # code references the deprecated constant, the callback prints the
57
+ # message and constantizes the replacement.
58
+ #
59
+ # Caveat: If the deprecated constant name is reachable in a different
60
+ # namespace and Ruby constant lookup finds it, the hook won't be
61
+ # called and the deprecation won't work as intended. This may happen,
62
+ # for example, if an ancestor of the enclosing namespace has a
63
+ # constant with the same name. This is an unsupported edge case.
64
+ def deprecate_constant ( old_constant_name , new_constant_path , deprecator :, message : nil )
43
65
class_variable_set ( :@@_deprecated_constants , { } ) unless class_variable_defined? ( :@@_deprecated_constants )
44
- class_variable_get ( :@@_deprecated_constants ) [ const_name . to_s ] = { new : new_constant , message : message , deprecator : deprecator }
66
+ class_variable_get ( :@@_deprecated_constants ) [ old_constant_name . to_s ] = { new : new_constant_path , message : message , deprecator : deprecator }
45
67
end
46
68
end
47
69
base . singleton_class . prepend extension
0 commit comments