Skip to content

Commit 3711c69

Browse files
george-mabyroot
authored andcommitted
Add :: to namespace the module we delegate "to"
Only namespace when the delegation object is a module
1 parent b16b516 commit 3711c69

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

activesupport/lib/active_support/delegation.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,19 @@ def generate(owner, methods, location: nil, to: nil, prefix: nil, allow_nil: nil
3939
location ||= caller_locations(1, 1).first
4040
file, line = location.path, location.lineno
4141

42-
receiver = to.to_s
42+
receiver = if to.is_a?(Module)
43+
if to.name.nil?
44+
raise ArgumentError, "Can't delegate to anonymous class or module: #{to}"
45+
end
46+
47+
unless Inflector.safe_constantize(to.name).equal?(to)
48+
raise ArgumentError, "Can't delegate to detached class or module: #{to.name}"
49+
end
50+
51+
"::#{to.name}"
52+
else
53+
to.to_s
54+
end
4355
receiver = "self.#{receiver}" if RESERVED_METHOD_NAMES.include?(receiver)
4456

4557
explicit_receiver = false

activesupport/test/core_ext/module_test.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,33 @@ def initialize(place)
586586
location.delegate(:street, :city, to: :@place, prefix: :the, private: true)
587587
end
588588

589+
def test_module_nesting_is_empty
590+
# Ensure constant resolution is done from top level namespace and not ActiveSupport
591+
require "json"
592+
c = Class.new do
593+
singleton_class.delegate :parse, to: ::JSON
594+
end
595+
assert_equal [1], c.parse("[1]")
596+
end
597+
598+
def test_delegation_unreacheable_module
599+
anonymous_class = Class.new
600+
error = assert_raises ArgumentError do
601+
Class.new do
602+
delegate :something, to: anonymous_class
603+
end
604+
end
605+
assert_includes error.message, "Can't delegate to anonymous class or module"
606+
607+
anonymous_class.singleton_class.define_method(:name) { "FakeName" }
608+
error = assert_raises ArgumentError do
609+
Class.new do
610+
delegate :something, to: anonymous_class
611+
end
612+
end
613+
assert_includes error.message, "Can't delegate to detached class or module: FakeName"
614+
end
615+
589616
def test_delegation_arity_to_module
590617
c = Class.new do
591618
delegate :zero, :one, :two, to: ArityTester

0 commit comments

Comments
 (0)