Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix problem with accessing deprecated constant proxy's subclass #36557

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 24 additions & 3 deletions activesupport/lib/active_support/deprecation/proxy_wrappers.rb
Expand Up @@ -120,7 +120,14 @@ def warn(callstack, called, args)
# # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
# (Backtrace information…)
# ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
class DeprecatedConstantProxy < DeprecationProxy
class DeprecatedConstantProxy < Module
def self.new(*args, &block)
sikachu marked this conversation as resolved.
Show resolved Hide resolved
object = args.first

return object unless object
super
end

def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
require "active_support/inflector/methods"

Expand All @@ -130,6 +137,14 @@ def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.ins
@message = message
end

instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }

# Don't give a deprecation warning on inspect since test/unit and error
# logs rely on it for diagnostics.
def inspect
target.inspect
end

# Returns the class of the new constant.
#
# PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
Expand All @@ -144,8 +159,14 @@ def target
ActiveSupport::Inflector.constantize(@new_const.to_s)
end

def warn(callstack, called, args)
@deprecator.warn(@message, callstack)
def const_missing(name)
@deprecator.warn(@message, caller_locations)
target.const_get(name)
end

def method_missing(called, *args, &block)
@deprecator.warn(@message, caller_locations)
target.__send__(called, *args, &block)
end
end
end
Expand Down
17 changes: 17 additions & 0 deletions activesupport/test/deprecation_test.rb
Expand Up @@ -38,6 +38,11 @@ module B
C = 1
end
A = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("Deprecatee::A", "Deprecatee::B::C")

module New
class Descendant; end
end
Old = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("Deprecatee::Old", "Deprecatee::New")
end

class DeprecateeWithAccessor
Expand Down Expand Up @@ -210,6 +215,18 @@ def test_deprecated_constant_proxy
assert_not_deprecated { assert_equal Deprecatee::B::C.class, Deprecatee::A.class }
end

def test_deprecated_constant_descendant
assert_not_deprecated { Deprecatee::New::Descendant }

assert_deprecated("Deprecatee::Old") do
assert_equal Deprecatee::Old::Descendant, Deprecatee::New::Descendant
end

assert_raises(NameError) do
assert_deprecated("Deprecatee::Old") { Deprecatee::Old::NON_EXISTENCE }
end
end

def test_deprecated_constant_accessor
assert_not_deprecated { DeprecateeWithAccessor::B::C }
assert_deprecated("DeprecateeWithAccessor::A") { assert_equal DeprecateeWithAccessor::B::C, DeprecateeWithAccessor::A }
Expand Down