From 6490d65234b89d4d28308b72b13d4834fd44bbb3 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 10 Mar 2011 19:04:00 +0000 Subject: Move the code which builds a scope for through associations into a generic AssociationScope class which is capable of building a scope for any association. --- .../associations/through_association.rb | 128 --------------------- 1 file changed, 128 deletions(-) (limited to 'activerecord/lib/active_record/associations/through_association.rb') diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index ae2c8b65ed..408237c689 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -1,5 +1,3 @@ -require 'enumerator' - module ActiveRecord # = Active Record Through Association module Associations @@ -26,77 +24,8 @@ module ActiveRecord scope end - def association_scope - scope = join_to(super) - - unless options[:include] - scope = scope.includes(source_options[:include]) - end - - scope - end - private - # This scope affects the creation of the associated records (not the join records). At the - # moment we only support creating on a :through association when the source reflection is a - # belongs_to. Thus it's not necessary to set a foreign key on the associated record(s), so - # this scope has can legitimately be empty. - def creation_attributes - { } - end - - # TODO: Needed? - def aliased_through_table - name = through_reflection.table_name - - reflection.table_name == name ? - through_reflection.klass.arel_table.alias(name + "_join") : - through_reflection.klass.arel_table - end - - def construct_owner_conditions - end - - def join_to(scope) - joins = [] - tables = tables().dup # FIXME: Ugly - - through_reflection_chain.each_with_index do |reflection, i| - table, foreign_table = tables.shift, tables.first - - if reflection.source_macro == :has_and_belongs_to_many - join_table = tables.shift - - joins << inner_join( - join_table, - table[reflection.active_record_primary_key]. - eq(join_table[reflection.association_foreign_key]) - ) - - table, foreign_table = join_table, tables.first - end - - if reflection.source_macro == :belongs_to - key = reflection.association_primary_key - foreign_key = reflection.foreign_key - else - key = reflection.foreign_key - foreign_key = reflection.active_record_primary_key - end - - if reflection == through_reflection_chain.last - constraint = table[key].eq owner[foreign_key] - scope = scope.where(constraint).where(reflection_conditions(i)) - else - constraint = table[key].eq foreign_table[foreign_key] - joins << inner_join(foreign_table, constraint, reflection_conditions(i)) - end - end - - scope.joins(joins) - end - # Construct attributes for :through pointing to owner and associate. This is used by the # methods which create and delete records on the association. # @@ -133,63 +62,6 @@ module ActiveRecord end end - def alias_tracker - @alias_tracker ||= AliasTracker.new - end - - def tables - @tables ||= begin - tables = [] - through_reflection_chain.each do |reflection| - tables << alias_tracker.aliased_table_for( - reflection.table_name, - table_alias_for(reflection, reflection != self.reflection) - ) - - if reflection.macro == :has_and_belongs_to_many || - (reflection.source_reflection && - reflection.source_reflection.macro == :has_and_belongs_to_many) - - tables << alias_tracker.aliased_table_for( - (reflection.source_reflection || reflection).options[:join_table], - table_alias_for(reflection, true) - ) - end - end - tables - end - end - - def table_alias_for(reflection, join = false) - name = alias_tracker.pluralize(reflection.name) - name << "_#{self.reflection.name}" - name << "_join" if join - name - end - - def inner_join(table, *conditions) - table.create_join( - table, - table.create_on(table.create_and(conditions.flatten.compact))) - end - - def reflection_conditions(index) - reflection = through_reflection_chain[index] - conditions = through_conditions[index] - - unless conditions.empty? - Arel::Nodes::And.new(process_conditions(conditions, reflection)) - end - end - - def process_conditions(conditions, reflection) - conditions.map do |condition| - condition = reflection.klass.send(:sanitize_sql, interpolate(condition), reflection.table_name) - condition = Arel.sql(condition) unless condition.is_a?(Arel::Node) - condition - end - end - # TODO: Think about this in the context of nested associations def stale_state if through_reflection.macro == :belongs_to -- cgit v1.2.3