Skip to content

Commit e98f4d8

Browse files
authored
Merge pull request rails#52305 from joshuay03/fix-52304
[Fix rails#52304] Avoid computing `klass` if reflection is a `belongs_to` in `ActiveRecord::AutosaveAssociation#inverse_belongs_to_association_for`
2 parents 69d904e + 38c1d5a commit e98f4d8

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

activerecord/lib/active_record/autosave_association.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,8 @@ def save_has_one_association(reflection)
467467
end
468468

469469
def inverse_belongs_to_association_for(reflection, record)
470-
reflection.inverse_of &&
470+
!reflection.belongs_to? &&
471+
reflection.inverse_of &&
471472
reflection.inverse_of.belongs_to? &&
472473
record.association(reflection.inverse_of.name)
473474
end

activerecord/test/cases/autosave_association_test.rb

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ def test_callbacks_firing_order_on_save
305305
end
306306

307307
def test_callbacks_on_child_when_parent_autosaves_child
308-
eye = Eye.create(iris: Iris.new)
308+
eye = Eye.create!(iris: Iris.new)
309309
assert_equal 1, eye.iris.before_validation_callbacks_counter
310310
assert_equal 1, eye.iris.before_create_callbacks_counter
311311
assert_equal 1, eye.iris.before_save_callbacks_counter
@@ -314,8 +314,18 @@ def test_callbacks_on_child_when_parent_autosaves_child
314314
assert_equal 1, eye.iris.after_save_callbacks_counter
315315
end
316316

317+
def test_callbacks_on_child_when_parent_autosaves_polymorphic_child_with_inverse_of
318+
drink_designer = DrinkDesigner.create!(chef: ChefWithPolymorphicInverseOf.new)
319+
assert_equal 1, drink_designer.chef.before_validation_callbacks_counter
320+
assert_equal 1, drink_designer.chef.before_create_callbacks_counter
321+
assert_equal 1, drink_designer.chef.before_save_callbacks_counter
322+
assert_equal 1, drink_designer.chef.after_validation_callbacks_counter
323+
assert_equal 1, drink_designer.chef.after_create_callbacks_counter
324+
assert_equal 1, drink_designer.chef.after_save_callbacks_counter
325+
end
326+
317327
def test_callbacks_on_child_when_child_autosaves_parent
318-
iris = Iris.create(eye: Eye.new)
328+
iris = Iris.create!(eye: Eye.new)
319329
assert_equal 1, iris.before_validation_callbacks_counter
320330
assert_equal 1, iris.before_create_callbacks_counter
321331
assert_equal 1, iris.before_save_callbacks_counter
@@ -324,6 +334,16 @@ def test_callbacks_on_child_when_child_autosaves_parent
324334
assert_equal 1, iris.after_save_callbacks_counter
325335
end
326336

337+
def test_callbacks_on_child_when_polymorphic_child_with_inverse_of_autosaves_parent
338+
chef = ChefWithPolymorphicInverseOf.create!(employable: DrinkDesigner.new)
339+
assert_equal 1, chef.before_validation_callbacks_counter
340+
assert_equal 1, chef.before_create_callbacks_counter
341+
assert_equal 1, chef.before_save_callbacks_counter
342+
assert_equal 1, chef.after_validation_callbacks_counter
343+
assert_equal 1, chef.after_create_callbacks_counter
344+
assert_equal 1, chef.after_save_callbacks_counter
345+
end
346+
327347
def test_foreign_key_attribute_is_not_set_unless_changed
328348
eye = Eye.create!(iris_with_read_only_foreign_key_attributes: { color: "honey" })
329349
assert_nothing_raised do

activerecord/test/models/chef.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,55 @@ class Chef < ActiveRecord::Base
88
class ChefList < Chef
99
belongs_to :employable_list, polymorphic: true
1010
end
11+
12+
class ChefWithPolymorphicInverseOf < Chef
13+
attr_reader :before_validation_callbacks_counter
14+
attr_reader :before_create_callbacks_counter
15+
attr_reader :before_save_callbacks_counter
16+
17+
attr_reader :after_validation_callbacks_counter
18+
attr_reader :after_create_callbacks_counter
19+
attr_reader :after_save_callbacks_counter
20+
21+
belongs_to :employable, polymorphic: true, inverse_of: :chef
22+
accepts_nested_attributes_for :employable
23+
24+
before_validation :update_before_validation_counter
25+
before_create :update_before_create_counter
26+
before_save :update_before_save_counter
27+
28+
after_validation :update_after_validation_counter
29+
after_create :update_after_create_counter
30+
after_save :update_after_save_counter
31+
32+
private
33+
def update_before_validation_counter
34+
@before_validation_callbacks_counter ||= 0
35+
@before_validation_callbacks_counter += 1
36+
end
37+
38+
def update_before_create_counter
39+
@before_create_callbacks_counter ||= 0
40+
@before_create_callbacks_counter += 1
41+
end
42+
43+
def update_before_save_counter
44+
@before_save_callbacks_counter ||= 0
45+
@before_save_callbacks_counter += 1
46+
end
47+
48+
def update_after_validation_counter
49+
@after_validation_callbacks_counter ||= 0
50+
@after_validation_callbacks_counter += 1
51+
end
52+
53+
def update_after_create_counter
54+
@after_create_callbacks_counter ||= 0
55+
@after_create_callbacks_counter += 1
56+
end
57+
58+
def update_after_save_counter
59+
@after_save_callbacks_counter ||= 0
60+
@after_save_callbacks_counter += 1
61+
end
62+
end

activerecord/test/models/drink_designer.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
class DrinkDesigner < ActiveRecord::Base
44
has_one :chef, as: :employable
5+
accepts_nested_attributes_for :chef
56
end
67

78
class DrinkDesignerWithPolymorphicDependentNullifyChef < ActiveRecord::Base

0 commit comments

Comments
 (0)