Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract aliasing code from JoinDependency and JoinAssociation into a …
…separate AliasTracker class. This can then be used by ThroughAssociationScope as well.
- Loading branch information
1 parent
c37a5e7
commit e887431
Showing
2 changed files
with
83 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
activerecord/lib/active_record/associations/alias_tracker.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,68 @@ | |||
require 'active_support/core_ext/string/conversions' | |||
|
|||
module ActiveRecord | |||
module Associations | |||
# Keeps track of table aliases for ActiveRecord::Associations::ClassMethods::JoinDependency | |||
class AliasTracker # :nodoc: | |||
# other_sql is some other sql which might conflict with the aliases we assign here. Therefore | |||
# we store other_sql so that we can scan it before assigning a specific name. | |||
def initialize(other_sql) | |||
@aliases = Hash.new | |||
@other_sql = other_sql.to_s.downcase | |||
end | |||
|
|||
def aliased_name_for(table_name, aliased_name = nil) | |||
aliased_name ||= table_name | |||
|
|||
initialize_count_for(table_name) if @aliases[table_name].nil? | |||
|
|||
if @aliases[table_name].zero? | |||
# If it's zero, we can have our table_name | |||
@aliases[table_name] = 1 | |||
table_name | |||
else | |||
# Otherwise, we need to use an alias | |||
aliased_name = connection.table_alias_for(aliased_name) | |||
|
|||
initialize_count_for(aliased_name) if @aliases[aliased_name].nil? | |||
|
|||
# Update the count | |||
@aliases[aliased_name] += 1 | |||
|
|||
if @aliases[aliased_name] > 1 | |||
"#{truncate(aliased_name)}_#{@aliases[aliased_name]}" | |||
else | |||
aliased_name | |||
end | |||
end | |||
end | |||
|
|||
private | |||
|
|||
def initialize_count_for(name) | |||
@aliases[name] = 0 | |||
|
|||
unless @other_sql.blank? | |||
# quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase | |||
quoted_name = connection.quote_table_name(name.downcase).downcase | |||
|
|||
# Table names | |||
@aliases[name] += @other_sql.scan(/join(?:\s+\w+)?\s+#{quoted_name}\son/).size | |||
|
|||
# Table aliases | |||
@aliases[name] += @other_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{quoted_name}\son/).size | |||
end | |||
|
|||
@aliases[name] | |||
end | |||
|
|||
def truncate(name) | |||
name[0..connection.table_alias_length-3] | |||
end | |||
|
|||
def connection | |||
ActiveRecord::Base.connection | |||
end | |||
end | |||
end | |||
end |