From 40ad4397c1f992ff506a85c7a33a940f9e81a092 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 9 Oct 2013 11:14:58 -0700 Subject: convert JoinBase to a tree and remove the Node class --- .../active_record/associations/join_dependency.rb | 52 +++++----------------- .../associations/join_dependency/join_part.rb | 20 ++++++++- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index d67e6aaaad..b852656c85 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -54,41 +54,15 @@ module ActiveRecord def initialize(base, associations, joins) @base_klass = base @table_joins = joins - @join_root = Node.new JoinBase.new(base) + @join_root = JoinBase.new(base) @alias_tracker = AliasTracker.new(base.connection, joins) @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 end - class Node # :nodoc: - include Enumerable - - attr_reader :join_part, :children - - def initialize(join_part) - @join_part = join_part - @children = [] - end - - def each - yield self - iter = lambda { |list| - list.each { |item| - yield item - iter.call item.children - } - } - iter.call children - end - - def name - join_part.reflection.name - end - end - def join_parts - @join_root.map(&:join_part) + @join_root.to_a end def graft(*associations) @@ -148,8 +122,7 @@ module ActiveRecord private def find_parent_node(parent) - @join_root.find { |node| - join_part = node.join_part + @join_root.find { |join_part| case parent when JoinBase parent.base_klass == join_part.base_klass @@ -160,7 +133,7 @@ module ActiveRecord end def join_base - @join_root.join_part + @join_root end def remove_duplicate_results!(base, records, associations) @@ -190,21 +163,19 @@ module ActiveRecord raise ConfigurationError, "Association named '#{ name }' was not found on #{ klass.name }; perhaps you misspelled it?" end - def build(associations, root, join_type) - parent = root.join_part + def build(associations, parent, join_type) associations.each do |name, right| reflection = find_reflection parent.base_klass, name join_association = build_join_association reflection, parent, join_type - root.children << join_association + parent.children << join_association build right, join_association, join_type end end - def find_or_build_scalar(reflection, node, join_type) - parent = node.join_part - unless join_association = find_join_association(reflection, node.join_part) + def find_or_build_scalar(reflection, parent, join_type) + unless join_association = find_join_association(reflection, parent) join_association = build_join_association(reflection, parent, join_type) - node.children << join_association + parent.children << join_association end join_association end @@ -228,13 +199,12 @@ module ActiveRecord raise EagerLoadPolymorphicError.new(reflection) end - part = JoinAssociation.new(reflection, join_parts.length, parent, join_type, alias_tracker) - Node.new part + JoinAssociation.new(reflection, join_parts.length, parent, join_type, alias_tracker) end def construct(parent, nodes, row, rs) nodes.sort_by { |k| k.name }.each do |node| - association = construct_association(parent, node.join_part, row, rs) + association = construct_association(parent, node, row, rs) construct(association, node.children, row, rs) if association end end diff --git a/activerecord/lib/active_record/associations/join_dependency/join_part.rb b/activerecord/lib/active_record/associations/join_dependency/join_part.rb index 2b6034ca9d..e27beb3b6f 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_part.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_part.rb @@ -8,10 +8,12 @@ module ActiveRecord # operations (for example a has_and_belongs_to_many JoinAssociation would result in # two; one for the join table and one for the target table). class JoinPart # :nodoc: + include Enumerable + # The Active Record class which this join part is associated 'about'; for a JoinBase # this is the actual base model, for a JoinAssociation this is the target model of the # association. - attr_reader :base_klass + attr_reader :base_klass, :children delegate :table_name, :column_names, :primary_key, :arel_engine, :to => :base_klass @@ -19,6 +21,22 @@ module ActiveRecord @base_klass = base_klass @cached_record = {} @column_names_with_alias = nil + @children = [] + end + + def name + reflection.name + end + + def each + yield self + iter = lambda { |list| + list.each { |item| + yield item + iter.call item.children + } + } + iter.call children end def aliased_table -- cgit v1.2.3