Skip to content

Commit 403743e

Browse files
committed
Fix alias_attribute to ignore methods defined in parent classes
Fix: rails#52144 When defining regular attributes, inherited methods aren't overriden, however when defining aliased attributes, inherited methods aren't considered. This behavior could be debatted, but that was the behavior prior to rails#52118, so I'm restoring it.
1 parent 98636b3 commit 403743e

File tree

3 files changed

+43
-17
lines changed

3 files changed

+43
-17
lines changed

activemodel/lib/active_model/attribute_methods.rb

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -312,26 +312,33 @@ def define_attribute_method(attr_name, _owner: generated_attribute_methods, as:
312312
end
313313
end
314314

315-
def define_attribute_method_pattern(pattern, attr_name, owner:, as:) # :nodoc:
315+
def define_attribute_method_pattern(pattern, attr_name, owner:, as:, override: false) # :nodoc:
316316
canonical_method_name = pattern.method_name(attr_name)
317317
public_method_name = pattern.method_name(as)
318318

319-
unless instance_method_already_implemented?(public_method_name)
320-
generate_method = "define_method_#{pattern.proxy_target}"
319+
# If defining a regular attribute method, we don't override methods that are explictly
320+
# defined in parrent classes.
321+
if instance_method_already_implemented?(public_method_name)
322+
# However, for `alias_attribute`, we always define the method.
323+
# We check for override second because `instance_method_already_implemented?`
324+
# also check for dangerous methods.
325+
return unless override
326+
end
321327

322-
if respond_to?(generate_method, true)
323-
send(generate_method, attr_name.to_s, owner: owner, as: as)
324-
else
325-
define_proxy_call(
326-
owner,
327-
canonical_method_name,
328-
pattern.proxy_target,
329-
pattern.parameters,
330-
attr_name.to_s,
331-
namespace: :active_model_proxy,
332-
as: public_method_name
333-
)
334-
end
328+
generate_method = "define_method_#{pattern.proxy_target}"
329+
330+
if respond_to?(generate_method, true)
331+
send(generate_method, attr_name.to_s, owner: owner, as: as)
332+
else
333+
define_proxy_call(
334+
owner,
335+
canonical_method_name,
336+
pattern.proxy_target,
337+
pattern.parameters,
338+
attr_name.to_s,
339+
namespace: :active_model_proxy,
340+
as: public_method_name
341+
)
335342
end
336343
end
337344

activerecord/lib/active_record/attribute_methods.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def alias_attribute_method_definition(code_generator, pattern, new_name, old_nam
9191
raise ArgumentError, "#{self.name} model aliases `#{old_name}`, but `#{old_name}` is not an attribute. " \
9292
"Use `alias_method :#{new_name}, :#{old_name}` or define the method manually."
9393
else
94-
define_attribute_method_pattern(pattern, old_name, owner: code_generator, as: new_name)
94+
define_attribute_method_pattern(pattern, old_name, owner: code_generator, as: new_name, override: true)
9595
end
9696
end
9797

activerecord/test/cases/attribute_methods_test.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,25 @@ def some_method_that_is_not_on_super
12171217
alias_attribute :subject, :title
12181218
end
12191219

1220+
test "#alias_attribute override methods defined in parent models" do
1221+
parent_model = Class.new(ActiveRecord::Base) do
1222+
self.abstract_class = true
1223+
1224+
def subject
1225+
"Abstract Subject"
1226+
end
1227+
end
1228+
1229+
subclass = Class.new(parent_model) do
1230+
self.table_name = "topics"
1231+
alias_attribute :subject, :title
1232+
end
1233+
1234+
obj = subclass.new
1235+
obj.title = "hey"
1236+
assert_equal("hey", obj.subject)
1237+
end
1238+
12201239
test "aliases to the same attribute name do not conflict with each other" do
12211240
first_model_object = ToBeLoadedFirst.new(author_name: "author 1")
12221241
assert_equal("author 1", first_model_object.subject)

0 commit comments

Comments
 (0)