diff options
author | wycats <wycats@gmail.com> | 2010-04-30 11:17:58 -0700 |
---|---|---|
committer | wycats <wycats@gmail.com> | 2010-04-30 11:17:58 -0700 |
commit | 0fe8827bf384cb99ab757236555c7af18793d515 (patch) | |
tree | a7ac2143c78964cad8ee87d9ff8a1c52abf61249 /activerecord/lib/active_record/associations.rb | |
parent | 91963e9e33eb5a28297323f1346aeb8b643e9d65 (diff) | |
parent | 6b559474fb7fae0160860fc62752da347af032b2 (diff) | |
download | rails-0fe8827bf384cb99ab757236555c7af18793d515.tar.gz rails-0fe8827bf384cb99ab757236555c7af18793d515.tar.bz2 rails-0fe8827bf384cb99ab757236555c7af18793d515.zip |
Merge branch 'master' of github.com:rails/rails
Diffstat (limited to 'activerecord/lib/active_record/associations.rb')
-rwxr-xr-x | activerecord/lib/active_record/associations.rb | 88 |
1 files changed, 70 insertions, 18 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index d94cc03938..6c64210c92 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1500,7 +1500,16 @@ module ActiveRecord when :destroy method_name = "has_many_dependent_destroy_for_#{reflection.name}".to_sym define_method(method_name) do - send(reflection.name).each { |o| o.destroy } + send(reflection.name).each do |o| + # No point in executing the counter update since we're going to destroy the parent anyway + counter_method = ('belongs_to_counter_cache_before_destroy_for_' + self.class.name.downcase).to_sym + if(o.respond_to? counter_method) then + class << o + self + end.send(:define_method, counter_method, Proc.new {}) + end + o.destroy + end end before_destroy method_name when :delete_all @@ -1728,6 +1737,14 @@ module ActiveRecord build(associations) end + def graft(*associations) + associations.each do |association| + join_associations.detect {|a| association == a} || + build(association.reflection.name, association.find_parent_in(self), association.join_class) + end + self + end + def join_associations @joins[1..-1].to_a end @@ -1736,6 +1753,16 @@ module ActiveRecord @joins[0] end + def count_aliases_from_table_joins(name) + quoted_name = join_base.active_record.connection.quote_table_name(name.downcase) + join_sql = join_base.table_joins.to_s.downcase + join_sql.blank? ? 0 : + # 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 + def instantiate(rows) rows.each_with_index do |row, i| primary_id = join_base.record_id(row) @@ -1780,22 +1807,22 @@ module ActiveRecord end protected - def build(associations, parent = nil) + def build(associations, parent = nil, join_class = Arel::InnerJoin) parent ||= @joins.last case associations when Symbol, String reflection = parent.reflections[associations.to_s.intern] or raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?" @reflections << reflection - @joins << build_join_association(reflection, parent) + @joins << build_join_association(reflection, parent).with_join_class(join_class) when Array associations.each do |association| - build(association, parent) + build(association, parent, join_class) end when Hash associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| - build(name, parent) - build(associations[name]) + build(name, parent, join_class) + build(associations[name], nil, join_class) end else raise ConfigurationError, associations.inspect @@ -1872,6 +1899,12 @@ module ActiveRecord @table_joins = joins end + def ==(other) + other.is_a?(JoinBase) && + other.active_record == active_record && + other.table_joins == table_joins + end + def aliased_prefix "t0" end @@ -1937,6 +1970,27 @@ module ActiveRecord end end + def ==(other) + other.is_a?(JoinAssociation) && + other.reflection == reflection && + other.parent == parent + end + + def find_parent_in(other_join_dependency) + other_join_dependency.joins.detect do |join| + self.parent == join + end + end + + def join_class + @join_class ||= Arel::InnerJoin + end + + def with_join_class(join_class) + @join_class = join_class + self + end + def association_join return @join if @join @@ -2036,27 +2090,25 @@ module ActiveRecord end def join_relation(joining_relation, join = nil) - if (relations = relation).is_a?(Array) - joining_relation.joins(Relation::JoinOperation.new(relations.first, Arel::OuterJoin, association_join.first)). - joins(Relation::JoinOperation.new(relations.last, Arel::OuterJoin, association_join.last)) - else - joining_relation.joins(Relation::JoinOperation.new(relations, Arel::OuterJoin, association_join)) - end + joining_relation.joins(self.with_join_class(Arel::OuterJoin)) end protected def aliased_table_name_for(name, suffix = nil) - if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{active_record.connection.quote_table_name name.downcase}\son} - @join_dependency.table_aliases[name] += 1 + if @join_dependency.table_aliases[name].zero? + @join_dependency.table_aliases[name] = @join_dependency.count_aliases_from_table_joins(name) end - unless @join_dependency.table_aliases[name].zero? - # if the table name has been used, then use an alias + if !@join_dependency.table_aliases[name].zero? # We need an alias name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}#{suffix}" - table_index = @join_dependency.table_aliases[name] @join_dependency.table_aliases[name] += 1 - name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0 + if @join_dependency.table_aliases[name] == 1 # First time we've seen this name + # Also need to count the aliases from the table_aliases to avoid incorrect count + @join_dependency.table_aliases[name] += @join_dependency.count_aliases_from_table_joins(name) + end + table_index = @join_dependency.table_aliases[name] + name = name[0..active_record.connection.table_alias_length-3] + "_#{table_index}" if table_index > 1 else @join_dependency.table_aliases[name] += 1 end |