aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/associations')
-rw-r--r--activerecord/lib/active_record/associations/association_collection.rb24
-rw-r--r--activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb28
2 files changed, 37 insertions, 15 deletions
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index f4e34657a5..f346a19a3a 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -218,9 +218,9 @@ module ActiveRecord
# are actually removed from the database, that depends precisely on
# +delete_records+. They are in any case removed from the collection.
def delete(*records)
- remove_records(records) do |records, old_records|
+ remove_records(records) do |_records, old_records|
delete_records(old_records) if old_records.any?
- records.each { |record| @target.delete(record) }
+ _records.each { |record| @target.delete(record) }
end
end
@@ -231,7 +231,7 @@ module ActiveRecord
# ignoring the +:dependent+ option.
def destroy(*records)
records = find(records) if records.any? {|record| record.kind_of?(Fixnum) || record.kind_of?(String)}
- remove_records(records) do |records, old_records|
+ remove_records(records) do |_records, old_records|
old_records.each { |record| record.destroy }
end
@@ -396,11 +396,12 @@ module ActiveRecord
if @target.is_a?(Array) && @target.any?
@target = find_target.map do |f|
i = @target.index(f)
- t = @target.delete_at(i) if i
- if t && t.changed?
- t
+ if i
+ @target.delete_at(i).tap do |t|
+ keys = ["id"] + t.changes.keys + (f.attribute_names - t.attribute_names)
+ t.attributes = f.attributes.except(*keys)
+ end
else
- f.mark_for_destruction if t && t.marked_for_destruction?
f
end
end + @target
@@ -477,7 +478,14 @@ module ActiveRecord
callback(:before_add, record)
yield(record) if block_given?
@target ||= [] unless loaded?
- @target << record unless @reflection.options[:uniq] && @target.include?(record)
+ index = @target.index(record)
+ unless @reflection.options[:uniq] && index
+ if index
+ @target[index] = record
+ else
+ @target << record
+ end
+ end
callback(:after_add, record)
set_inverse_instance(record, @owner)
record
diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
index c989c3536d..e61af93d1e 100644
--- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
@@ -45,17 +45,23 @@ module ActiveRecord
if @reflection.options[:insert_sql]
@owner.connection.insert(interpolate_sql(@reflection.options[:insert_sql], record))
else
- relation = Arel::Table.new(@reflection.options[:join_table])
+ relation = Arel::Table.new(@reflection.options[:join_table])
+ timestamps = record_timestamp_columns(record)
+ timezone = record.send(:current_time_from_proper_timezone) if timestamps.any?
+
attributes = columns.inject({}) do |attrs, column|
- case column.name.to_s
+ name = column.name
+ case name.to_s
when @reflection.primary_key_name.to_s
- attrs[relation[column.name]] = owner_quoted_id
+ attrs[relation[name]] = @owner.id
when @reflection.association_foreign_key.to_s
- attrs[relation[column.name]] = record.quoted_id
+ attrs[relation[name]] = record.id
+ when *timestamps
+ attrs[relation[name]] = timezone
else
- if record.has_attribute?(column.name)
- value = @owner.send(:quote_value, record[column.name], column)
- attrs[relation[column.name]] = value unless value.nil?
+ if record.has_attribute?(name)
+ value = @owner.send(:quote_value, record[name], column)
+ attrs[relation[name]] = value unless value.nil?
end
end
attrs
@@ -117,6 +123,14 @@ module ActiveRecord
build_record(attributes, &block)
end
end
+
+ def record_timestamp_columns(record)
+ if record.record_timestamps
+ record.send(:all_timestamp_attributes).map(&:to_s)
+ else
+ []
+ end
+ end
end
end
end