aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2013-10-11 18:38:19 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2013-10-11 18:38:19 -0700
commitcfbb6eeb4c778c974399c5196e1ecb9cdafca277 (patch)
treea2c4a6d25c6ec7a88190cb1c0cdee9c92ead7dad
parentd9a7f86666a8f4345fc2b4680ec9b407294a6cc0 (diff)
downloadrails-cfbb6eeb4c778c974399c5196e1ecb9cdafca277.tar.gz
rails-cfbb6eeb4c778c974399c5196e1ecb9cdafca277.tar.bz2
rails-cfbb6eeb4c778c974399c5196e1ecb9cdafca277.zip
keep track of AR objects we've made as we walk the tree
Remove duplicate removal code because we avoid adding duplicates as we walk the tree the first time
-rw-r--r--activerecord/lib/active_record/associations/join_dependency.rb57
1 files changed, 22 insertions, 35 deletions
diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb
index 6457880e65..4daaec9d22 100644
--- a/activerecord/lib/active_record/associations/join_dependency.rb
+++ b/activerecord/lib/active_record/associations/join_dependency.rb
@@ -97,14 +97,21 @@ module ActiveRecord
type_caster = result_set.column_type primary_key
+ seen = Hash.new { |h,parent_klass|
+ h[parent_klass] = Hash.new { |i,parent_id|
+ i[parent_id] = Hash.new { |j,child_klass|
+ j[child_klass] = {}
+ }
+ }
+ }
+
records = result_set.map { |row_hash|
primary_id = type_caster.type_cast row_hash[primary_key]
parent = parents[primary_id] ||= join_root.instantiate(row_hash)
- construct(parent, join_root, row_hash, result_set)
+ construct(parent, join_root, row_hash, result_set, seen)
parent
}.uniq
- remove_duplicate_results!(base_klass, records, join_root.children)
records
end
@@ -147,28 +154,6 @@ module ActiveRecord
dup
end
- def remove_duplicate_results!(base, records, associations)
- associations.each do |node|
- reflection = node.reflection
- remove_uniq_by_reflection(reflection, records)
-
- parent_records = []
- records.each do |record|
- if descendant = record.send(reflection.name)
- if reflection.collection?
- parent_records.concat descendant.target.uniq
- else
- parent_records << descendant
- end
- end
- end
-
- unless parent_records.empty?
- remove_duplicate_results!(reflection.klass, parent_records, node.children)
- end
- end
- end
-
def find_reflection(klass, name)
klass.reflect_on_association(name) or
raise ConfigurationError, "Association named '#{ name }' was not found on #{ klass.name }; perhaps you misspelled it?"
@@ -188,12 +173,6 @@ module ActiveRecord
parent.children << join_association
end
- def remove_uniq_by_reflection(reflection, records)
- if reflection.collection?
- records.each { |record| record.send(reflection.name).target.uniq! }
- end
- end
-
def build_join_association(reflection, parent, join_type)
reflection.check_validity!
@@ -206,7 +185,7 @@ module ActiveRecord
node
end
- def construct(ar_parent, parent, row, rs)
+ def construct(ar_parent, parent, row, rs, seen)
primary_key = parent.aliased_primary_key
type_caster = rs.column_type primary_key
@@ -219,15 +198,23 @@ module ActiveRecord
else
if ar_parent.association_cache.key?(node.reflection.name)
model = ar_parent.association(node.reflection.name).target
- construct(model, node, row, rs)
+ construct(model, node, row, rs, seen)
next
end
end
- next if row[node.aliased_primary_key].nil?
+ id = row[node.aliased_primary_key]
+ next if id.nil?
+
+ model = seen[parent.base_klass][primary_id][node.base_klass][id]
- model = construct_model(ar_parent, node, row)
- construct(model, node, row, rs)
+ if model
+ construct(model, node, row, rs, seen)
+ else
+ model = construct_model(ar_parent, node, row)
+ seen[parent.base_klass][primary_id][node.base_klass][id] = model
+ construct(model, node, row, rs, seen)
+ end
end
end
end