From 4c045876da051694aa4b9c69dd708283c5e2879d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 24 Sep 2013 17:21:19 -0700 Subject: push slice loading to it's own method so we can remove the type casting code --- .../associations/preloader/association.rb | 21 ++++++++------------ .../preloader/has_and_belongs_to_many.rb | 23 +++++++++++----------- 2 files changed, 20 insertions(+), 24 deletions(-) (limited to 'activerecord/lib/active_record/associations') diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 63161d9744..cc8eefb234 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -3,9 +3,6 @@ module ActiveRecord class Preloader class Association #:nodoc: attr_reader :owners, :reflection, :preload_scope, :model, :klass - attr_reader :type_caster - - IDENTITY_CASTER = lambda { |value| value } # :nodoc: def initialize(klass, owners, reflection, preload_scope) @klass = klass @@ -15,7 +12,6 @@ module ActiveRecord @model = owners.first && owners.first.class @scope = nil @owners_by_key = nil - @type_caster = IDENTITY_CASTER @associated_records_by_owner = nil end @@ -90,15 +86,9 @@ module ActiveRecord # Some databases impose a limit on the number of ids in a list (in Oracle it's 1000) # Make several smaller queries if necessary or make one query if the adapter supports it sliced = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size) - records = sliced.flat_map { |slice| - records = records_for(slice) - set_type_caster records, association_key_name - records - } - caster = type_caster - records.each do |record| - owner_key = caster.call record[association_key_name] + records = load_slices sliced + records.each do |record, owner_key| owners_map[owner_key].each do |owner| records_by_owner[owner] << record end @@ -111,7 +101,12 @@ module ActiveRecord @associated_records_by_owner = records_by_owner end - def set_type_caster(results, name) + def load_slices(slices) + slices.flat_map { |slice| + records_for(slice).to_a.map! { |record| + [record, record[association_key_name]] + } + } end def reflection_scope diff --git a/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb index 1c119d739f..996575f5aa 100644 --- a/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +++ b/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb @@ -33,18 +33,19 @@ module ActiveRecord # Once we have used the join table column (in super), we manually instantiate the # actual records, ensuring that we don't create more than one instances of the same # record - def associated_records_by_owner(preloader) - return @associated_records_by_owner if @associated_records_by_owner + def load_slices(slices) + identity_map = {} + caster = nil + name = association_key_name - records = {} - @associated_records_by_owner = super.each_value do |rows| - rows.map! { |row| records[row[klass.primary_key]] ||= klass.instantiate(row) } - end - end - - def set_type_caster(results, name) - caster = results.column_types.fetch(name, results.identity_type) - @type_caster = lambda { |value| caster.type_cast value } + slices.flat_map { |slice| + records = records_for(slice) + caster ||= records.column_types.fetch(name, records.identity_type) + records.map! { |row| + record = identity_map[row[klass.primary_key]] ||= klass.instantiate(row) + [record, caster.type_cast(row[name])] + } + } end def build_scope -- cgit v1.2.3