diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2018-06-26 05:46:09 +0900 |
---|---|---|
committer | Ryuta Kamizono <kamipo@gmail.com> | 2018-07-03 03:07:59 +0900 |
commit | 0255cf94b0871230aba106543c17918caafbef0e (patch) | |
tree | bf4b3caeb30ac5bcfa11570e91d81cca74b9c466 /activerecord | |
parent | e4282e2fbf00711c374fdb67c0842952f2b227f7 (diff) | |
download | rails-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.rb | 4 | ||||
-rw-r--r-- | activerecord/test/cases/associations/eager_test.rb | 18 |
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, |