diff options
author | Eileen M. Uchitelle <eileencodes@users.noreply.github.com> | 2018-10-04 11:03:24 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-04 11:03:24 -0400 |
commit | ddac80a951beb307d5d7adb781f6dd1d1f169f7e (patch) | |
tree | e35255c49833c6cb4b15d3774acb76f98c33d8f5 /activerecord/lib/active_record/associations | |
parent | 414c70e072466ebe40e7c46795f27c48cba8d717 (diff) | |
parent | d634c0d82b8ebd7b019baed535d89541bc8e4f6a (diff) | |
download | rails-ddac80a951beb307d5d7adb781f6dd1d1f169f7e.tar.gz rails-ddac80a951beb307d5d7adb781f6dd1d1f169f7e.tar.bz2 rails-ddac80a951beb307d5d7adb781f6dd1d1f169f7e.zip |
Merge pull request #33938 from faucct/bugfix/preload_through_no_records
ActiveRecord::Associations::Preloader should not fail to preload through missing records
Diffstat (limited to 'activerecord/lib/active_record/associations')
-rw-r--r-- | activerecord/lib/active_record/associations/preloader.rb | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb index a8f94b574d..9253f4ccb4 100644 --- a/activerecord/lib/active_record/associations/preloader.rb +++ b/activerecord/lib/active_record/associations/preloader.rb @@ -98,12 +98,14 @@ module ActiveRecord # Loads all the given data into +records+ for the +association+. def preloaders_on(association, records, scope, polymorphic_parent = false) - if association.respond_to?(:to_hash) + case association + when Hash preloaders_for_hash(association, records, scope, polymorphic_parent) - elsif association.is_a?(Symbol) - preloaders_for_one(association, records, scope, polymorphic_parent) - elsif association.respond_to?(:to_str) - preloaders_for_one(association.to_sym, records, scope, polymorphic_parent) + when Symbol, String + grouped_records(association.to_sym, records, polymorphic_parent) + .flat_map do |reflection, reflection_records| + preloaders_for_reflection reflection, reflection_records, scope + end else raise ArgumentError, "#{association.inspect} was not recognized for preload" end @@ -111,17 +113,15 @@ module ActiveRecord def preloaders_for_hash(association, records, scope, polymorphic_parent) association.flat_map { |parent, child| - loaders = preloaders_for_one parent, records, scope, polymorphic_parent - - recs = loaders.flat_map(&:preloaded_records).uniq - - reflection = records.first.class._reflect_on_association(parent) - polymorphic_parent = reflection && reflection.options[:polymorphic] - - loaders.concat Array.wrap(child).flat_map { |assoc| - preloaders_on assoc, recs, scope, polymorphic_parent - } - loaders + grouped_records(parent, records, polymorphic_parent).flat_map do |reflection, reflection_records| + loaders = preloaders_for_reflection(reflection, reflection_records, scope) + recs = loaders.flat_map(&:preloaded_records) + child_polymorphic_parent = reflection && reflection.options[:polymorphic] + loaders.concat Array.wrap(child).flat_map { |assoc| + preloaders_on assoc, recs, scope, child_polymorphic_parent + } + loaders + end } end @@ -137,13 +137,11 @@ module ActiveRecord # Additionally, polymorphic belongs_to associations can have multiple associated # classes, depending on the polymorphic_type field. So we group by the classes as # well. - def preloaders_for_one(association, records, scope, polymorphic_parent) - grouped_records(association, records, polymorphic_parent).flat_map do |reflection, klasses| - klasses.map do |rhs_klass, rs| - loader = preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope) - loader.run self - loader - end + def preloaders_for_reflection(reflection, records, scope) + records.group_by { |record| record.association(reflection.name).klass }.map do |rhs_klass, rs| + loader = preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope) + loader.run self + loader end end @@ -151,11 +149,9 @@ module ActiveRecord h = {} records.each do |record| next unless record - next if polymorphic_parent && !record.class._reflect_on_association(association) - assoc = record.association(association) - next unless assoc.klass - klasses = h[assoc.reflection] ||= {} - (klasses[assoc.klass] ||= []) << record + reflection = record.class._reflect_on_association(association) + next if polymorphic_parent && !reflection || !record.association(association).klass + (h[reflection] ||= []) << record end h end |