diff options
-rw-r--r-- | activerecord/lib/active_record/associations/join_dependency.rb | 76 |
1 files changed, 19 insertions, 57 deletions
diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index 7e5a8728ee..dab8b75b5c 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -58,41 +58,22 @@ module ActiveRecord @alias_tracker.aliased_name_for(base.table_name) # Updates the count for base.table_name to 1 tree = self.class.make_tree associations build tree, @join_root, Arel::InnerJoin - apply_tables! @join_root + @join_root.children.each { |child| construct_tables! @join_root, child } end def reflections join_root.drop(1).map!(&:reflection) end - def merge_outer_joins!(other) - left = join_root - right = other.join_root - - if left.match? right - merge_node left, right - else - # If the roots aren't the same, then deep copy the RHS to the LHS - left.children.concat right.children.map { |node| - deep_copy left, node - } - end - apply_tables! @join_root - end - - def apply_tables!(node) - node.children.each { |child| construct_tables! node, child } - end - def join_constraints(outer_joins) - joins = make_joins join_root + joins = make_inner_joins join_root joins.concat outer_joins.flat_map { |oj| if join_root.match? oj.join_root walk join_root, oj.join_root else oj.join_root.children.flat_map { |child| - make_the_joins(join_root, child) + make_outer_joins(join_root, child) } end } @@ -173,24 +154,25 @@ module ActiveRecord private - def make_the_joins(parent, child) + def make_constraints(parent, child, tables, join_type) chain = child.reflection.chain foreign_table = parent.table foreign_klass = parent.base_klass - tables = table_aliases_for(parent, child) - join_type = Arel::OuterJoin + child.join_constraints(foreign_table, foreign_klass, child, join_type, tables, child.reflection.scope_chain, chain) + end + + def make_outer_joins(parent, child) + tables = table_aliases_for(parent, child) + join_type = Arel::OuterJoin + joins = make_constraints parent, child, tables, join_type - joins = child.join_constraints(foreign_table, foreign_klass, child, join_type, tables, child.reflection.scope_chain, chain) - joins.concat child.children.flat_map { |c| make_the_joins(child, c) } + joins.concat child.children.flat_map { |c| make_outer_joins(child, c) } end - def make_joins(node) - node.children.flat_map { |child| - chain = child.reflection.chain - foreign_table = node.table - foreign_klass = node.base_klass - child.join_constraints(foreign_table, foreign_klass, child, child.join_type, child.tables, child.reflection.scope_chain, chain) - .concat make_joins(child) + def make_inner_joins(parent) + parent.children.flat_map { |child| + joins = make_constraints(parent, child, child.tables, Arel::InnerJoin) + joins.concat make_inner_joins(child) } end @@ -204,7 +186,7 @@ module ActiveRecord end def construct_tables!(parent, node) - node.tables = table_aliases_for(parent, node) unless node.tables + node.tables = table_aliases_for(parent, node) node.children.each { |child| construct_tables! node, child } end @@ -219,29 +201,10 @@ module ActiveRecord [left.children.find { |node2| node1.match? node2 }, node1] }.partition(&:first) - ojs = missing.flat_map { |_,n| - make_the_joins left, n - } - + ojs = missing.flat_map { |_,n| make_outer_joins left, n } intersection.flat_map { |l,r| walk l, r }.concat ojs end - def merge_node(left, right) - intersection, missing = right.children.map { |node1| - [left.children.find { |node2| node1.match? node2 }, node1] - }.partition(&:first) - - intersection.each { |l,r| merge_node l, r } - - left.children.concat missing.map { |_,node| deep_copy left, node } - end - - def deep_copy(parent, node) - dup = build_join_association(node.reflection, parent, Arel::OuterJoin) - dup.children.concat node.children.map { |n| deep_copy dup, n } - dup - 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?" @@ -263,8 +226,7 @@ module ActiveRecord raise EagerLoadPolymorphicError.new(reflection) end - node = JoinAssociation.new(reflection, join_type) - node + JoinAssociation.new(reflection, join_type) end def construct(ar_parent, parent, row, rs, seen, model_cache, aliases) |