diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2013-10-11 18:38:19 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2013-10-11 18:38:19 -0700 |
commit | cfbb6eeb4c778c974399c5196e1ecb9cdafca277 (patch) | |
tree | a2c4a6d25c6ec7a88190cb1c0cdee9c92ead7dad /activerecord/lib | |
parent | d9a7f86666a8f4345fc2b4680ec9b407294a6cc0 (diff) | |
download | rails-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
Diffstat (limited to 'activerecord/lib')
-rw-r--r-- | activerecord/lib/active_record/associations/join_dependency.rb | 57 |
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 |