From 5b0b3cce5c0ecef02f1f6f09aea1de44b9ca88cf Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 11 Nov 2014 14:10:42 -0500 Subject: Move `#alias_name` to `ReflectionProxy` class Putting the `#alias_name` into ReflectionProxy means we don't have to cache the `#alias_name` globally anymore - it's not cached per query. --- .../associations/association_scope.rb | 33 +++++++++++++++------- activerecord/lib/active_record/reflection.rb | 10 ------- 2 files changed, 23 insertions(+), 20 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index b5a6954554..48288496c4 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -159,32 +159,45 @@ module ActiveRecord end def alias_name(name, alias_tracker) - alias_name = "#{plural_name}_#{name}_join" - table_name = klass.table_name - alias_tracker.aliased_table_for(table_name, alias_name) + @alias ||= begin + alias_name = "#{plural_name}_#{name}_join" + table_name = klass.table_name + alias_tracker.aliased_table_for(table_name, alias_name) + end + end + end + + class ReflectionProxy < SimpleDelegator + def alias_name(name, alias_tracker) + @alias ||= begin + alias_name = "#{plural_name}_#{name}" + alias_tracker.aliased_table_for(table_name, alias_name) + end end end def get_chain(reflection, association) - chain = reflection.chain.dup + chain = reflection.chain.map { |reflection| + ReflectionProxy.new(reflection) + } chain[0] = RuntimeReflection.new(reflection, association) chain end def add_constraints(scope, owner, assoc_klass, refl, tracker, chain) - tables = construct_tables(chain, tracker, refl.name) - + construct_tables(chain, tracker, refl.name) owner_reflection = chain.last - table = tables.last - scope = last_chain_scope(scope, table, owner_reflection, owner, connection, assoc_klass) + table = owner_reflection.alias_name(refl.name, tracker) + scope = last_chain_scope(scope, table, owner_reflection, owner, tracker, assoc_klass) # chain.first always == refl chain.each_with_index do |reflection, i| - table, foreign_table = tables.shift, tables.first + table = reflection.alias_name(refl.name, tracker) unless reflection == chain.last next_reflection = chain[i + 1] - scope = next_chain_scope(scope, table, reflection, connection, assoc_klass, foreign_table, next_reflection) + foreign_table = next_reflection.alias_name(refl.name, tracker) + scope = next_chain_scope(scope, table, reflection, tracker, assoc_klass, foreign_table, next_reflection) end # Exclude the scope of the association itself, because that diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 83771bd5dc..1bc92b1587 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -165,11 +165,6 @@ module ActiveRecord def constraints scope ? [scope] : [] end - - def alias_name(name, alias_tracker) - alias_name = "#{plural_name}_#{name}" - alias_tracker.aliased_table_for(table_name, alias_name) - end end # Base class for AggregateReflection and AssociationReflection. Objects of @@ -758,11 +753,6 @@ module ActiveRecord source_type = @prev_reflection.options[:source_type] lambda { |object| where(type => source_type) } end - - def alias_name(name, alias_tracker) - alias_name = "#{plural_name}_#{name}" - alias_tracker.aliased_table_for(table_name, alias_name) - end end # Consider the following example: -- cgit v1.2.3