Permalink
Browse files

push slice loading to it's own method so we can remove the type casting

code
  • Loading branch information...
1 parent c4e1fdd commit 4c045876da051694aa4b9c69dd708283c5e2879d @tenderlove tenderlove committed Sep 25, 2013
@@ -3,9 +3,6 @@ module Associations
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 @@ def initialize(klass, owners, reflection, preload_scope)
@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 @@ def associated_records_by_owner(preloader)
# 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 @@ def associated_records_by_owner(preloader)
@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
@@ -33,18 +33,19 @@ def association_key
# 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

0 comments on commit 4c04587

Please sign in to comment.