aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/associations
diff options
context:
space:
mode:
authorJohn Hawthorn <john@stembolt.com>2017-06-20 17:35:13 -0700
committerJohn Hawthorn <john@stembolt.com>2017-06-20 17:40:08 -0700
commitc7f669af6f1d8e9053a586c97584702971e1906c (patch)
treedb0526246e0c33a617d8dcf106a88ffe07efa2de /activerecord/test/cases/associations
parent0787727cd65d820df78c9cd71ac9f145c9834762 (diff)
downloadrails-c7f669af6f1d8e9053a586c97584702971e1906c.tar.gz
rails-c7f669af6f1d8e9053a586c97584702971e1906c.tar.bz2
rails-c7f669af6f1d8e9053a586c97584702971e1906c.zip
Clear offset cache on CollectionProxy reset/reload
The `@offsets` cache is used by FinderMethods to cache records found by find_nth. This cache is cleared in AR::Relation#reset, but not in CollectionProxy#reset or CollectionProxy#reload. Because of this, since #29098, calling #first/#find_nth/etc after calling #reload or #reset on an association could return a stale record. This is an issue both when the full association target is loaded and when the item is loaded in #find_nth. This commit solves the problem by clearing the `@offsets` cache in CollectionProxy#reset and CollectionProxy#reload.
Diffstat (limited to 'activerecord/test/cases/associations')
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb26
1 files changed, 26 insertions, 0 deletions
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 590d3642bd..ae58dbff21 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -741,6 +741,32 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal client2, firm.clients.merge!(where: ["#{QUOTED_TYPE} = :type", { type: "Client" }], order: "id").first
end
+ def test_find_first_after_reset
+ firm = Firm.all.merge!(order: "id").first
+
+ # Calling first twice should return the same object
+ original_object_id = firm.clients.first.object_id
+ assert_equal firm.clients.first.object_id, original_object_id, "Expected multiple invocations of #first to return the same object"
+
+ firm.clients.reset
+
+ # It should return a different object, since the association has been reloaded
+ assert_not_equal original_object_id, firm.clients.first.object_id, "Expected #first after #reload to return a new object"
+ end
+
+ def test_find_first_after_reload
+ firm = Firm.all.merge!(order: "id").first
+
+ # Calling first twice should return the same object
+ original_object_id = firm.clients.first.object_id
+ assert_equal firm.clients.first.object_id, original_object_id, "Expected multiple invocations of #first to return the same object"
+
+ firm.clients.reload
+
+ # It should return a different object, since the association has been reloaded
+ assert_not_equal original_object_id, firm.clients.first.object_id, "Expected #first after #reload to return a new object"
+ end
+
def test_find_all_with_include_and_conditions
assert_nothing_raised do
Developer.all.merge!(joins: :audit_logs, where: { "audit_logs.message" => nil, :name => "Smith" }).to_a