4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
# File 'lib/identity_map/active_record/association_preload.rb', line 4
def preload_has_and_belongs_to_many_association_with_identity_map(records, reflection, preload_options={})
unless reflection.klass.respond_to?(:id_map)
return preload_has_and_belongs_to_many_association_without_identity_map(records, reflection, preload_options)
end
table_name = reflection.klass.quoted_table_name
records = records.find_all{|record| !record.send(reflection.name).loaded?}
return if records.empty?
id_to_record_map, ids = construct_id_map(records)
records.each {|record| record.send(reflection.name).loaded}
options = reflection.options
conditions = "t0.#{reflection.primary_key_name} #{in_or_equals_for_ids(ids)}"
conditions << append_conditions(reflection, preload_options)
joins = connection.select_all(sanitize_sql([
"select t0.#{reflection.primary_key_name} as prnt_id, t0.#{reflection.association_foreign_key} as chld_id
from #{connection.quote_table_name options[:join_table]} t0
where #{conditions}
", ids]))
child_record_ids = joins.map{|j| j['chld_id']}.uniq
associated_records = reflection.klass.with_exclusive_scope do
reflection.klass.find(:all, :conditions => {reflection.klass.primary_key => child_record_ids},
:include => options[:include],
:select => options[:select].presence,
:order => options[:order])
end
associated_record_map = associated_records.inject({}){|h, r| h[r.id.to_s] = r; h}
joins.each do |j|
mapped_records = id_to_record_map[j['prnt_id'].to_s]
add_preloaded_records_to_collection(mapped_records, reflection.name, associated_record_map[j['chld_id'].to_s])
end
end
|