Skip to content

Commit 94d24f4

Browse files
committed
[R] Remove deprecated support to call alias_attribute with non-existent attribute names
1 parent 2af68b2 commit 94d24f4

File tree

4 files changed

+109
-136
lines changed

4 files changed

+109
-136
lines changed

activerecord/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Remove deprecated support to call `alias_attribute` with non-existent attribute names.
2+
3+
*Rafael Mendonça França*
4+
15
* Remove deprecated `Rails.application.config.active_record.suppress_multiple_database_warning`.
26

37
*Rafael Mendonça França*

activerecord/lib/active_record/attribute_methods.rb

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -78,38 +78,15 @@ def eagerly_generate_alias_attribute_methods(_new_name, _old_name) # :nodoc:
7878
end
7979

8080
def alias_attribute_method_definition(code_generator, pattern, new_name, old_name)
81-
method_name = pattern.method_name(new_name).to_s
82-
target_name = pattern.method_name(old_name).to_s
83-
parameters = pattern.parameters
8481
old_name = old_name.to_s
8582

86-
method_defined = method_defined?(target_name) || private_method_defined?(target_name)
87-
manually_defined = method_defined &&
88-
!self.instance_method(target_name).owner.is_a?(GeneratedAttributeMethods)
89-
reserved_method_name = ::ActiveRecord::AttributeMethods.dangerous_attribute_methods.include?(target_name)
90-
9183
if !abstract_class? && !has_attribute?(old_name)
92-
# We only need to issue this deprecation warning once, so we issue it when defining the original reader method.
93-
should_warn = target_name == old_name
94-
if should_warn
95-
ActiveRecord.deprecator.warn(
96-
"#{self} model aliases `#{old_name}`, but `#{old_name}` is not an attribute. " \
97-
"Starting in Rails 7.2, alias_attribute with non-attribute targets will raise. " \
98-
"Use `alias_method :#{new_name}, :#{old_name}` or define the method manually."
99-
)
100-
end
101-
super
102-
elsif manually_defined && !reserved_method_name
103-
aliased_method_redefined_as_well = method_defined_within?(method_name, self)
104-
return if aliased_method_redefined_as_well
105-
106-
ActiveRecord.deprecator.warn(
107-
"#{self} model aliases `#{old_name}` and has a method called `#{target_name}` defined. " \
108-
"Starting in Rails 7.2 `#{method_name}` will not be calling `#{target_name}` anymore. " \
109-
"You may want to additionally define `#{method_name}` to preserve the current behavior."
110-
)
111-
super
84+
raise ArgumentError, "#{self.name} model aliases `#{old_name}`, but `#{old_name}` is not an attribute. " \
85+
"Use `alias_method :#{new_name}, :#{old_name}` or define the method manually."
11286
else
87+
method_name = pattern.method_name(new_name).to_s
88+
parameters = pattern.parameters
89+
11390
define_proxy_call(code_generator, method_name, pattern.proxy_target, parameters, old_name,
11491
namespace: :proxy_alias_attribute
11592
)

activerecord/test/cases/attribute_methods_test.rb

Lines changed: 98 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,57 +1234,39 @@ def some_method_that_is_not_on_super
12341234
assert_equal("foo", second_model_object.subject)
12351235
end
12361236

1237-
ClassWithDeprecatedAliasAttributeBehavior = Class.new(ActiveRecord::Base) do
1238-
self.table_name = "topics"
1239-
alias_attribute :subject, :title
1237+
test "#alias_attribute with an overridden original method does not use the overridden original method" do
1238+
class_with_deprecated_alias_attribute_behavior = Class.new(ActiveRecord::Base) do
1239+
self.table_name = "topics"
1240+
alias_attribute :subject, :title
12401241

1241-
def title_was
1242-
"overridden_title_was"
1242+
def title_was
1243+
"overridden_title_was"
1244+
end
12431245
end
1244-
end
12451246

1246-
test "#alias_attribute with an overridden original method issues a deprecation" do
1247-
message = <<~MESSAGE.gsub("\n", " ")
1248-
AttributeMethodsTest::ClassWithDeprecatedAliasAttributeBehavior model aliases
1249-
`title` and has a method called `title_was` defined.
1250-
Starting in Rails 7.2 `subject_was` will not be calling `title_was` anymore.
1251-
You may want to additionally define `subject_was` to preserve the current behavior.
1252-
MESSAGE
1253-
1254-
obj = assert_deprecated(message, ActiveRecord.deprecator) do
1255-
ClassWithDeprecatedAliasAttributeBehavior.new
1256-
end
1247+
obj = class_with_deprecated_alias_attribute_behavior.new
12571248
obj.title = "hey"
12581249
assert_equal("hey", obj.subject)
1259-
assert_equal("overridden_title_was", obj.subject_was)
1250+
assert_nil(obj.subject_was)
12601251
end
12611252

1262-
TitleWasOverride = Module.new do
1263-
def title_was
1264-
"overridden_title_was"
1253+
test "#alias_attribute with an overridden original method from a module does not use the overridden original method" do
1254+
title_was_override = Module.new do
1255+
def title_was
1256+
"overridden_title_was"
1257+
end
12651258
end
1266-
end
12671259

1268-
ClassWithDeprecatedAliasAttributeBehaviorFromModule = Class.new(ActiveRecord::Base) do
1269-
self.table_name = "topics"
1270-
include TitleWasOverride
1271-
alias_attribute :subject, :title
1272-
end
1273-
1274-
test "#alias_attribute with an overridden original method from a module issues a deprecation" do
1275-
message = <<~MESSAGE.gsub("\n", " ")
1276-
AttributeMethodsTest::ClassWithDeprecatedAliasAttributeBehaviorFromModule model aliases
1277-
`title` and has a method called `title_was` defined.
1278-
Starting in Rails 7.2 `subject_was` will not be calling `title_was` anymore.
1279-
You may want to additionally define `subject_was` to preserve the current behavior.
1280-
MESSAGE
1281-
1282-
obj = assert_deprecated(message, ActiveRecord.deprecator) do
1283-
ClassWithDeprecatedAliasAttributeBehaviorFromModule.new
1260+
class_with_deprecated_alias_attribute_behavior_from_module = Class.new(ActiveRecord::Base) do
1261+
self.table_name = "topics"
1262+
include title_was_override
1263+
alias_attribute :subject, :title
12841264
end
1265+
1266+
obj = class_with_deprecated_alias_attribute_behavior_from_module.new
12851267
obj.title = "hey"
12861268
assert_equal("hey", obj.subject)
1287-
assert_equal("overridden_title_was", obj.subject_was)
1269+
assert_nil(obj.subject_was)
12881270
end
12891271

12901272
ClassWithDeprecatedAliasAttributeBehaviorResolved = Class.new(ActiveRecord::Base) do
@@ -1300,22 +1282,17 @@ def subject_was
13001282
end
13011283
end
13021284

1303-
class ChildWithDeprecatedBehaviorResolved < ClassWithDeprecatedAliasAttributeBehaviorResolved
1304-
end
1305-
1306-
test "#alias_attribute with an overridden original method along with an overridden alias method doesn't issue a deprecation" do
1307-
obj = assert_not_deprecated(ActiveRecord.deprecator) do
1308-
ClassWithDeprecatedAliasAttributeBehaviorResolved.new
1309-
end
1285+
test "#alias_attribute with an overridden original method along with an overridden alias method uses the overridden alias method" do
1286+
obj = ClassWithDeprecatedAliasAttributeBehaviorResolved.new
13101287
obj.title = "hey"
13111288
assert_equal("hey", obj.subject)
13121289
assert_equal("overridden_subject_was", obj.subject_was)
13131290
end
13141291

1315-
test "#alias_attribute with an overridden original method along with an overridden alias method in a parent class doesn't issue a deprecation" do
1316-
obj = assert_not_deprecated(ActiveRecord.deprecator) do
1317-
ChildWithDeprecatedBehaviorResolved.new
1318-
end
1292+
test "#alias_attribute with an overridden original method along with an overridden alias method in a parent class uses the overridden alias method" do
1293+
child_with_deprecated_behavior_resolved = Class.new(ClassWithDeprecatedAliasAttributeBehaviorResolved)
1294+
1295+
obj = child_with_deprecated_behavior_resolved.new
13191296
obj.title = "hey"
13201297
assert_equal("hey", obj.subject)
13211298
assert_equal("overridden_subject_was", obj.subject_was)
@@ -1355,58 +1332,78 @@ class ChildWithDeprecatedBehaviorResolved < ClassWithDeprecatedAliasAttributeBeh
13551332
assert_equal 123_456, object.id_value
13561333
end
13571334

1358-
ClassWithGeneratedAttributeMethodTarget = Class.new(ActiveRecord::Base) do
1359-
self.table_name = "topics"
1360-
alias_attribute :saved_title, :title_in_database
1361-
end
1335+
test "#alias_attribute with an _in_database method issues raises an error" do
1336+
class_with_generated_attribute_method_target = Class.new(ActiveRecord::Base) do
1337+
def self.name
1338+
"ClassWithGeneratedAttributeMethodTarget"
1339+
end
1340+
1341+
self.table_name = "topics"
1342+
1343+
alias_attribute :saved_title, :title_in_database
1344+
end
13621345

1363-
test "#alias_attribute with an _in_database method issues a deprecation warning" do
1364-
message = <<~MESSAGE.gsub("\n", " ")
1365-
AttributeMethodsTest::ClassWithGeneratedAttributeMethodTarget model aliases
1346+
message = <<~MESSAGE.squish
1347+
ClassWithGeneratedAttributeMethodTarget model aliases
13661348
`title_in_database`, but `title_in_database` is not an attribute.
1367-
Starting in Rails 7.2, alias_attribute with non-attribute targets will raise.
13681349
Use `alias_method :saved_title, :title_in_database` or define the method manually.
13691350
MESSAGE
13701351

1371-
obj = assert_deprecated(message, ActiveRecord.deprecator) do
1372-
ClassWithGeneratedAttributeMethodTarget.new
1352+
error = assert_raises(ArgumentError) do
1353+
class_with_generated_attribute_method_target.new
13731354
end
1374-
obj.title = "A river runs through it"
1375-
assert_nil obj.saved_title
1376-
obj.save
1377-
assert_equal "A river runs through it", obj.saved_title
1355+
1356+
assert_equal message, error.message
13781357
end
13791358

1380-
ClassWithEnumMethodTarget = Class.new(ActiveRecord::Base) do
1381-
self.table_name = "books"
1359+
test "#alias_attribute with enum method raises an error" do
1360+
class_with_enum_method_target = Class.new(ActiveRecord::Base) do
1361+
def self.name
1362+
"ClassWithEnumMethodTarget"
1363+
end
13821364

1383-
attribute :status, :string
1365+
self.table_name = "books"
13841366

1385-
enum :status, {
1386-
pending: "0",
1387-
completed: "1",
1388-
}
1389-
alias_attribute :is_pending?, :pending?
1390-
end
1367+
attribute :status, :string
13911368

1392-
test "#alias_attribute with enum method issues a deprecation warning" do
1393-
message = <<~MESSAGE.gsub("\n", " ")
1394-
AttributeMethodsTest::ClassWithEnumMethodTarget model aliases `pending?`, but `pending?` is not an attribute. Starting in Rails 7.2, alias_attribute with non-attribute targets will raise. Use `alias_method :is_pending?, :pending?` or define the method manually.
1369+
enum :status, {
1370+
pending: "0",
1371+
completed: "1",
1372+
}
1373+
alias_attribute :is_pending?, :pending?
1374+
end
1375+
1376+
message = <<~MESSAGE.squish
1377+
ClassWithEnumMethodTarget model aliases `pending?`, but `pending?` is not an attribute. Use `alias_method :is_pending?, :pending?` or define the method manually.
13951378
MESSAGE
13961379

1397-
obj = assert_deprecated(message, ActiveRecord.deprecator) do
1398-
ClassWithEnumMethodTarget.new
1380+
error = assert_raises(ArgumentError) do
1381+
class_with_enum_method_target.new
13991382
end
1400-
obj.status = "pending"
1401-
assert_predicate obj, :pending?
1402-
assert_predicate obj, :is_pending?
1383+
assert_equal message, error.message
14031384
end
14041385

1405-
ClassWithAssociationTarget = Class.new(ActiveRecord::Base) do
1406-
self.table_name = "books"
1407-
belongs_to :author
1386+
test "#alias_attribute with an association method raises an error" do
1387+
class_with_association_target = Class.new(ActiveRecord::Base) do
1388+
def self.name
1389+
"ClassWithAssociationTarget"
1390+
end
1391+
1392+
self.table_name = "books"
1393+
1394+
belongs_to :author
1395+
1396+
alias_attribute :written_by, :author
1397+
end
14081398

1409-
alias_attribute :written_by, :author
1399+
message = <<~MESSAGE.squish
1400+
ClassWithAssociationTarget model aliases `author`, but `author` is not an attribute. Use `alias_method :written_by, :author` or define the method manually.
1401+
MESSAGE
1402+
1403+
error = assert_raises(ArgumentError) do
1404+
class_with_association_target.new
1405+
end
1406+
assert_equal message, error.message
14101407
end
14111408

14121409
test "#alias_attribute method on a STI class is available on subclasses" do
@@ -1425,38 +1422,31 @@ class ChildWithDeprecatedBehaviorResolved < ClassWithDeprecatedAliasAttributeBeh
14251422
assert_equal "Text", comment.text
14261423
end
14271424

1428-
test "#alias_attribute with an association method issues a deprecation warning" do
1429-
message = <<~MESSAGE.gsub("\n", " ")
1430-
AttributeMethodsTest::ClassWithAssociationTarget model aliases `author`, but `author` is not an attribute. Starting in Rails 7.2, alias_attribute with non-attribute targets will raise. Use `alias_method :written_by, :author` or define the method manually.
1431-
MESSAGE
14321425

1433-
obj = assert_deprecated(message, ActiveRecord.deprecator) do
1434-
ClassWithAssociationTarget.new
1435-
end
1436-
obj.author = Author.new(name: "Octavia E. Butler")
1437-
assert_equal "Octavia E. Butler", obj.written_by.name
1438-
end
1426+
test "#alias_attribute with a manually defined method raises an error" do
1427+
class_with_aliased_manually_defined_method = Class.new(ActiveRecord::Base) do
1428+
def self.name
1429+
"ClassWithAliasedManuallyDefinedMethod"
1430+
end
14391431

1440-
ClassWithAliasedManuallyDefinedMethod = Class.new(ActiveRecord::Base) do
1441-
self.table_name = "books"
1442-
alias_attribute :print, :publish
1432+
self.table_name = "books"
14431433

1444-
def publish
1445-
"Publishing!"
1434+
alias_attribute :print, :publish
1435+
1436+
def publish
1437+
"Publishing!"
1438+
end
14461439
end
1447-
end
14481440

1449-
test "#alias_attribute with a manually defined method issues a deprecation warning" do
1450-
message = <<~MESSAGE.gsub("\n", " ")
1451-
AttributeMethodsTest::ClassWithAliasedManuallyDefinedMethod model aliases `publish`,
1452-
but `publish` is not an attribute.
1453-
Starting in Rails 7.2, alias_attribute with non-attribute targets will raise.
1441+
message = <<~MESSAGE.squish
1442+
ClassWithAliasedManuallyDefinedMethod model aliases `publish`, but `publish` is not an attribute.
14541443
Use `alias_method :print, :publish` or define the method manually.
14551444
MESSAGE
14561445

1457-
assert_deprecated(message, ActiveRecord.deprecator) do
1458-
ClassWithAliasedManuallyDefinedMethod.new
1446+
error = assert_raises(ArgumentError) do
1447+
class_with_aliased_manually_defined_method.new
14591448
end
1449+
assert_equal message, error.message
14601450
end
14611451

14621452
private

guides/source/7_2_release_notes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ Please refer to the [Changelog][active-record] for detailed changes.
107107

108108
* Remove deprecated `Rails.application.config.active_record.suppress_multiple_database_warning`.
109109

110+
* Remove deprecated support to call `alias_attribute` with non-existent attribute names.
111+
110112
### Deprecations
111113

112114
### Notable changes

0 commit comments

Comments
 (0)