Skip to content

Commit 3272335

Browse files
authored
Merge pull request rails#43448 from composerinteralia/stale-inversed-target
Make inversed association stale after updating id
2 parents 46bb4de + 9c8fab9 commit 3272335

File tree

4 files changed

+35
-11
lines changed

4 files changed

+35
-11
lines changed

activerecord/lib/active_record/associations/association.rb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ def reset
5252
@loaded = false
5353
@target = nil
5454
@stale_state = nil
55-
@inversed = false
5655
end
5756

5857
def reset_negative_cache # :nodoc:
@@ -78,7 +77,6 @@ def loaded?
7877
def loaded!
7978
@loaded = true
8079
@stale_state = stale_state
81-
@inversed = false
8280
end
8381

8482
# The target is stale if the target no longer points to the record(s) that the
@@ -88,7 +86,7 @@ def loaded!
8886
#
8987
# Note that if the target has not been loaded, it is not considered stale.
9088
def stale_target?
91-
!@inversed && loaded? && @stale_state != stale_state
89+
loaded? && @stale_state != stale_state
9290
end
9391

9492
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
@@ -137,15 +135,11 @@ def remove_inverse_instance(record)
137135

138136
def inversed_from(record)
139137
self.target = record
140-
@inversed = !!record
141138
end
142139

143140
def inversed_from_queries(record)
144141
if inversable?(record)
145142
self.target = record
146-
@inversed = true
147-
else
148-
@inversed = false
149143
end
150144
end
151145

activerecord/lib/active_record/autosave_association.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,8 @@ def save_collection_association(reflection)
404404
saved = true
405405

406406
if autosave != false && (new_record_before_save || record.new_record?)
407+
association.set_inverse_instance(record)
408+
407409
if autosave
408410
saved = association.insert_record(record, false)
409411
elsif !reflection.nested?
@@ -447,9 +449,7 @@ def save_has_one_association(reflection)
447449
if (autosave && record.changed_for_autosave?) || record_changed?(reflection, record, key)
448450
unless reflection.through_reflection
449451
record[reflection.foreign_key] = key
450-
if inverse_reflection = reflection.inverse_of
451-
record.association(inverse_reflection.name).inversed_from(self)
452-
end
452+
association.set_inverse_instance(record)
453453
end
454454

455455
saved = record.save(validate: !autosave)

activerecord/test/cases/associations/has_many_associations_test.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1440,7 +1440,7 @@ def test_calling_update_on_id_changes_the_counter_cache
14401440
assert_equal original_count, topic.reload.replies_count
14411441
end
14421442

1443-
def test_calling_update_changing_ids_doesnt_change_counter_cache
1443+
def test_calling_update_changing_ids_changes_the_counter_cache
14441444
topic1 = Topic.find(1)
14451445
topic2 = Topic.find(3)
14461446
original_count1 = topic1.replies.to_a.size
@@ -1458,6 +1458,24 @@ def test_calling_update_changing_ids_doesnt_change_counter_cache
14581458
assert_equal original_count2, topic2.reload.replies_count
14591459
end
14601460

1461+
def test_calling_update_changing_ids_of_inversed_association_changes_the_counter_cache
1462+
assert_predicate Post.reflect_on_association(:comments), :has_inverse?
1463+
1464+
post1 = Post.first
1465+
post2 = Post.second
1466+
1467+
original_count1 = post1.comments.count
1468+
original_count2 = post2.comments.count
1469+
1470+
post1.comments.first.update(post_id: post2.id)
1471+
assert_equal original_count1 - 1, post1.reload.comments_count
1472+
assert_equal original_count2 + 1, post2.reload.comments_count
1473+
1474+
post2.comments.first.update(post_id: post1.id)
1475+
assert_equal original_count1, post1.reload.comments_count
1476+
assert_equal original_count2, post2.reload.comments_count
1477+
end
1478+
14611479
def test_deleting_a_collection
14621480
force_signal37_to_load_all_clients_of_firm
14631481

activerecord/test/cases/associations/inverse_associations_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,18 @@ def test_inverse_works_when_the_association_self_references_the_same_object
664664
comment.body = "OMG"
665665
assert_equal comment.body, comment.children.first.parent.body
666666
end
667+
668+
def test_changing_the_association_id_makes_the_inversed_association_target_stale
669+
post1 = Post.first
670+
post2 = Post.second
671+
comment = post1.comments.first
672+
673+
assert_same post1, comment.post
674+
675+
comment.update!(post_id: post2.id)
676+
677+
assert_equal post2, comment.post
678+
end
667679
end
668680

669681
class InverseBelongsToTests < ActiveRecord::TestCase

0 commit comments

Comments
 (0)