aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2018-06-26 05:46:09 +0900
committerRyuta Kamizono <kamipo@gmail.com>2018-07-03 03:07:59 +0900
commit0255cf94b0871230aba106543c17918caafbef0e (patch)
treebf4b3caeb30ac5bcfa11570e91d81cca74b9c466 /activerecord
parente4282e2fbf00711c374fdb67c0842952f2b227f7 (diff)
downloadrails-0255cf94b0871230aba106543c17918caafbef0e.tar.gz
rails-0255cf94b0871230aba106543c17918caafbef0e.tar.bz2
rails-0255cf94b0871230aba106543c17918caafbef0e.zip
Don't share seen object cache between different join nodes in eager loading
Currently, the seen object cache is shared if join nodes have the same target class. But it is a wrong assumption, we can't share the seen object cache between different join nodes (e.g. `:readonly_account` and `:accounts` have the same target class `Account`, but the instances have the different state `readonly`). Fixes #26805. Closes #27737.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/join_dependency.rb4
-rw-r--r--activerecord/test/cases/associations/eager_test.rb18
2 files changed, 20 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb
index 8cf1b5d25a..be56d27021 100644
--- a/activerecord/lib/active_record/associations/join_dependency.rb
+++ b/activerecord/lib/active_record/associations/join_dependency.rb
@@ -225,7 +225,7 @@ module ActiveRecord
next
end
- model = seen[ar_parent.object_id][node.base_klass][id]
+ model = seen[ar_parent.object_id][node][id]
if model
construct(model, node, row, seen, model_cache)
@@ -237,7 +237,7 @@ module ActiveRecord
model.readonly!
end
- seen[ar_parent.object_id][node.base_klass][id] = model
+ seen[ar_parent.object_id][node][id] = model
construct(model, node, row, seen, model_cache)
end
end
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 8be663e3dc..5b8d4722af 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -123,6 +123,24 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal memberships(:membership_of_boring_club), member.current_membership
end
+ def test_loading_associations_dont_leak_instance_state
+ assertions = ->(firm) {
+ assert_equal companies(:first_firm), firm
+
+ assert_predicate firm.association(:readonly_account), :loaded?
+ assert_predicate firm.association(:accounts), :loaded?
+
+ assert_equal accounts(:signals37), firm.readonly_account
+ assert_equal [accounts(:signals37)], firm.accounts
+
+ assert_predicate firm.readonly_account, :readonly?
+ assert firm.accounts.none?(&:readonly?)
+ }
+
+ assertions.call(Firm.preload(:readonly_account, :accounts).first)
+ assertions.call(Firm.eager_load(:readonly_account, :accounts).first)
+ end
+
def test_with_ordering
list = Post.all.merge!(includes: :comments, order: "posts.id DESC").to_a
[:other_by_mary, :other_by_bob, :misc_by_mary, :misc_by_bob, :eager_other,