diff options
Diffstat (limited to 'activerecord/lib/active_record/associations/has_many_association.rb')
-rw-r--r-- | activerecord/lib/active_record/associations/has_many_association.rb | 79 |
1 files changed, 13 insertions, 66 deletions
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 978fc74560..b07441f3c6 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -6,19 +6,7 @@ module ActiveRecord # If the association has a <tt>:through</tt> option further specialization # is provided by its child HasManyThroughAssociation. class HasManyAssociation < AssociationCollection #:nodoc: - def initialize(owner, reflection) - @finder_sql = nil - super - end protected - def owner_quoted_id - if @reflection.options[:primary_key] - quote_value(@owner.send(@reflection.options[:primary_key])) - else - @owner.quoted_id - end - end - # Returns the number of records in this collection. # # If the association has a counter cache it gets that value. Otherwise @@ -35,10 +23,10 @@ module ActiveRecord def count_records count = if has_cached_counter? @owner.send(:read_attribute, cached_counter_attribute_name) - elsif @reflection.options[:counter_sql] - @reflection.klass.count_by_sql(@counter_sql) + elsif @reflection.options[:counter_sql] || @reflection.options[:finder_sql] + @reflection.klass.count_by_sql(custom_counter_sql) else - @reflection.klass.count(:conditions => @counter_sql, :include => @reflection.options[:include]) + scoped.count end # If there's nothing in the database and @target has no new records @@ -46,11 +34,7 @@ module ActiveRecord # documented side-effect of the method that may avoid an extra SELECT. @target ||= [] and loaded if count == 0 - if @reflection.options[:limit] - count = [ @reflection.options[:limit], count ].min - end - - return count + [@reflection.options[:limit], count].compact.min end def has_cached_counter? @@ -62,8 +46,8 @@ module ActiveRecord end def insert_record(record, force = false, validate = true) - set_belongs_to_association_for(record) - force ? record.save! : record.save(:validate => validate) + set_owner_attributes(record) + save_record(record, force, validate) end # Deletes the records according to the <tt>:dependent</tt> option. @@ -72,57 +56,20 @@ module ActiveRecord when :destroy records.each { |r| r.destroy } when :delete_all - @reflection.klass.delete(records.map { |record| record.id }) + @reflection.klass.delete(records.map { |r| r.id }) else - relation = Arel::Table.new(@reflection.table_name) - relation.where(relation[@reflection.primary_key_name].eq(@owner.id). - and(relation[@reflection.klass.primary_key].in(records.map { |r| r.id })) - ).update(relation[@reflection.primary_key_name] => nil) + updates = { @reflection.foreign_key => nil } + conditions = { @reflection.association_primary_key => records.map { |r| r.id } } - @owner.class.update_counters(@owner.id, cached_counter_attribute_name => -records.size) if has_cached_counter? + scoped.where(conditions).update_all(updates) end - end - - def target_obsolete? - false - end - - def construct_sql - case - when @reflection.options[:finder_sql] - @finder_sql = interpolate_sql(@reflection.options[:finder_sql]) - when @reflection.options[:as] - @finder_sql = - "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " + - "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}" - @finder_sql << " AND (#{conditions})" if conditions - - else - @finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}" - @finder_sql << " AND (#{conditions})" if conditions + if has_cached_counter? && @reflection.options[:dependent] != :destroy + @owner.class.update_counters(@owner.id, cached_counter_attribute_name => -records.size) end - - construct_counter_sql - end - - def construct_scope - create_scoping = {} - set_belongs_to_association_for(create_scoping) - { - :find => { :conditions => @finder_sql, - :readonly => false, - :order => @reflection.options[:order], - :limit => @reflection.options[:limit], - :include => @reflection.options[:include]}, - :create => create_scoping - } end - def we_can_set_the_inverse_on_this?(record) - inverse = @reflection.inverse_of - return !inverse.nil? - end + alias creation_attributes construct_owner_attributes end end end |