Skip to content

Commit 78b6d93

Browse files
committed
If an attribute alias reaches method missing, send the original
Fixes rails#51717
1 parent d65fec4 commit 78b6d93

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

activemodel/lib/active_model/attribute_methods.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,10 @@ def method_missing(method, ...)
480480
if respond_to_without_attributes?(method, true)
481481
super
482482
else
483+
# If the missing method is an attribute alias, let's dispatch the original.
484+
if self.class.attribute_alias?(method) && self.class.send(:instance_method_already_implemented?, method)
485+
method = self.class.attribute_alias(method).to_sym
486+
end
483487
match = matched_attribute_method(method.name)
484488
match ? attribute_missing(match, ...) : super
485489
end
@@ -505,7 +509,7 @@ def respond_to?(method, include_private_methods = false)
505509
# but found among all methods. Which means that the given method is private.
506510
false
507511
else
508-
!matched_attribute_method(method.to_s).nil?
512+
self.class.send(:instance_method_already_implemented?, method) || !matched_attribute_method(method.to_s).nil?
509513
end
510514
end
511515

activemodel/test/cases/attribute_methods_test.rb

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ def attributes
1919
def attribute(name)
2020
attributes[name.to_sym]
2121
end
22+
23+
def attribute_method?(name)
24+
attributes.include?(name.to_sym)
25+
end
2226
end
2327

2428
class ModelWithAttributes2
@@ -236,11 +240,11 @@ def foo
236240
end
237241

238242
test "#undefine_attribute_methods removes attribute methods" do
239-
ModelWithAttributes.define_attribute_methods(:foo)
240-
ModelWithAttributes.undefine_attribute_methods
243+
ModelWithoutAttributesMethod.define_attribute_methods(:foo)
244+
assert_respond_to ModelWithoutAttributesMethod.new, :foo
241245

242-
assert_not_respond_to ModelWithAttributes.new, :foo
243-
assert_raises(NoMethodError) { ModelWithAttributes.new.foo }
246+
ModelWithoutAttributesMethod.undefine_attribute_methods
247+
assert_not_respond_to ModelWithoutAttributesMethod.new, :foo
244248
end
245249

246250
test "#undefine_attribute_methods undefines alias attribute methods" do
@@ -341,6 +345,25 @@ def m.attribute_missing(match, *args, &block)
341345
assert_equal "attribute_test", match.proxy_target
342346
end
343347

348+
test "should use attribute_missing to dispatch a missing attribute alias" do
349+
klass = Class.new(ModelWithAttributes) do
350+
define_attribute_method(:foo)
351+
alias_attribute :foo2, :foo
352+
end
353+
354+
m = klass.new
355+
def m.attribute_missing(match, ...)
356+
match
357+
end
358+
klass.undef_method :foo
359+
klass.undef_method :foo2
360+
361+
match = m.foo2
362+
363+
assert_equal "foo", match.attr_name
364+
assert_equal "attribute", match.proxy_target
365+
end
366+
344367
module NameClash
345368
class Model1
346369
include ActiveModel::AttributeMethods

0 commit comments

Comments
 (0)