aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/class_methods/join_dependency.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/associations/class_methods/join_dependency.rb')
-rw-r--r--activerecord/lib/active_record/associations/class_methods/join_dependency.rb37
1 files changed, 27 insertions, 10 deletions
diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb
index c578845878..13576e1aec 100644
--- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb
+++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb
@@ -6,14 +6,17 @@ module ActiveRecord
module Associations
module ClassMethods
class JoinDependency # :nodoc:
- attr_reader :join_parts, :reflections, :table_aliases
+ attr_reader :join_parts, :reflections, :table_aliases, :active_record
def initialize(base, associations, joins)
- @table_joins = joins || ''
+ @active_record = base
+ @table_joins = joins
@join_parts = [JoinBase.new(base)]
@associations = {}
@reflections = []
- @table_aliases = Hash.new(0)
+ @table_aliases = Hash.new do |h,name|
+ h[name] = count_aliases_from_table_joins(name)
+ end
@table_aliases[base.table_name] = 1
build(associations)
end
@@ -44,12 +47,26 @@ module ActiveRecord
end
def count_aliases_from_table_joins(name)
+ return 0 if !@table_joins || Arel::Table === @table_joins
+
+ @table_joins.grep(Arel::Nodes::Join).map { |join|
+ right = join.right
+ case right
+ when Arel::Table
+ right.name.downcase == name ? 1 : 0
+ when String
+ count_aliases_from_string(right.downcase, name)
+ else
+ 0
+ end
+ }.sum
+ end
+
+ def count_aliases_from_string(join_sql, name)
# quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase
- quoted_name = join_base.active_record.connection.quote_table_name(name.downcase).downcase
- join_sql = @table_joins.downcase
- join_sql.blank? ? 0 :
- # Table names
- join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size +
+ quoted_name = active_record.connection.quote_table_name(name.downcase).downcase
+ # Table names
+ join_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size +
# Table aliases
join_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{quoted_name}\son/).size
end
@@ -61,11 +78,11 @@ module ActiveRecord
records = rows.map { |model|
primary_id = model[primary_key]
parent = parents[primary_id] ||= join_base.instantiate(model)
- construct(parent, @associations, join_associations.dup, model)
+ construct(parent, @associations, join_associations, model)
parent
}.uniq
- remove_duplicate_results!(join_base.active_record, records, @associations)
+ remove_duplicate_results!(active_record, records, @associations)
records
end