From bd4eff2f99ffa5868574c497bc63f320cbda3083 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev Date: Wed, 13 Feb 2019 12:25:43 +0200 Subject: Fix reset of the source association when through association is loaded The special case happens when through association has a custom scope that is applied to the source association when loading. In this case, the soucre association would need to be reset after main association is loaded. See tests. The special case exists when a through association has --- .../associations/preloader/association.rb | 2 +- .../associations/preloader/through_association.rb | 29 +++++++--------------- 2 files changed, 10 insertions(+), 21 deletions(-) (limited to 'activerecord/lib/active_record/associations/preloader') diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index d6f7359055..85a994b27a 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -116,7 +116,7 @@ module ActiveRecord def build_scope scope = klass.scope_for_association - if reflection.type + if reflection.type && !reflection.through_reflection? scope.where!(reflection.type => model.polymorphic_name) end diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index a6b7ab80a2..25254e652a 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -7,10 +7,9 @@ module ActiveRecord def run(preloader) already_loaded = owners.first.association(through_reflection.name).loaded? through_scope = through_scope() - reflection_scope = target_reflection_scope through_preloaders = preloader.preload(owners, through_reflection.name, through_scope) middle_records = through_preloaders.flat_map(&:preloaded_records) - preloaders = preloader.preload(middle_records, source_reflection.name, reflection_scope) + preloaders = preloader.preload(middle_records, source_reflection.name, scope) @preloaded_records = preloaders.flat_map(&:preloaded_records) owners.each do |owner| @@ -25,18 +24,18 @@ module ActiveRecord owner.association(through_reflection.name).reset if through_scope end result = through_records.flat_map do |record| - association = record.association(source_reflection.name) - target = association.target - association.reset if preload_scope - target + record.association(source_reflection.name).target end result.compact! - if reflection_scope - result.sort_by! { |rhs| preload_index[rhs] } if reflection_scope.order_values.any? - result.uniq! if reflection_scope.distinct_value - end + result.sort_by! { |rhs| preload_index[rhs] } if scope.order_values.any? + result.uniq! if scope.distinct_value associate_records_to_owner(owner, result) end + unless scope.empty_scope? + middle_records.each do |owner| + owner.association(source_reflection.name).reset + end + end end private @@ -91,16 +90,6 @@ module ActiveRecord scope unless scope.empty_scope? end - - def target_reflection_scope - if preload_scope - reflection_scope.merge(preload_scope) - elsif reflection.scope - reflection_scope - else - nil - end - end end end end -- cgit v1.2.3