aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2011-05-31 20:32:09 +0100
committerJon Leighton <j@jonathanleighton.com>2011-05-31 20:32:09 +0100
commitdfaad4f5a78b2e21a3b86e0daea3afb3b483dc5e (patch)
treea0235d7f4c62d9a075c6cba36d8e2b653a349fd5 /activerecord
parentaa316e27b7f6f17328f2be6c481f7d9ee3a92f86 (diff)
downloadrails-dfaad4f5a78b2e21a3b86e0daea3afb3b483dc5e.tar.gz
rails-dfaad4f5a78b2e21a3b86e0daea3afb3b483dc5e.tar.bz2
rails-dfaad4f5a78b2e21a3b86e0daea3afb3b483dc5e.zip
Only save the record once when calling create! on a collection association. Fixes #1360.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb40
-rw-r--r--activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb10
-rw-r--r--activerecord/lib/active_record/associations/has_many_association.rb9
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb11
4 files changed, 45 insertions, 25 deletions
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index d0ab6b4b86..02cc455a4e 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -104,26 +104,11 @@ module ActiveRecord
end
def create(attributes = {}, options = {}, &block)
- unless owner.persisted?
- raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
- end
-
- if attributes.is_a?(Array)
- attributes.collect { |attr| create(attr, options, &block) }
- else
- transaction do
- add_to_target(build_record(attributes, options)) do |record|
- yield(record) if block_given?
- insert_record(record)
- end
- end
- end
+ create_record(attributes, options, &block)
end
- def create!(attrs = {}, options = {}, &block)
- record = create(attrs, options, &block)
- Array.wrap(record).each(&:save!)
- record
+ def create!(attributes = {}, options = {}, &block)
+ create_record(attributes, options, true, &block)
end
# Add +records+ to this association. Returns +self+ so method calls may be chained.
@@ -422,8 +407,25 @@ module ActiveRecord
persisted + memory
end
+ def create_record(attributes, options, raise = false, &block)
+ unless owner.persisted?
+ raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
+ end
+
+ if attributes.is_a?(Array)
+ attributes.collect { |attr| create_record(attr, options, raise, &block) }
+ else
+ transaction do
+ add_to_target(build_record(attributes, options)) do |record|
+ yield(record) if block_given?
+ insert_record(record, true, raise)
+ end
+ end
+ end
+ end
+
# Do the relevant stuff to insert the given record into the association collection.
- def insert_record(record, validate = true)
+ def insert_record(record, validate = true, raise = false)
raise NotImplementedError
end
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 217213808b..f7ce70db1a 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
@@ -9,8 +9,14 @@ module ActiveRecord
super
end
- def insert_record(record, validate = true)
- return if record.new_record? && !record.save(:validate => validate)
+ def insert_record(record, validate = true, raise = false)
+ if record.new_record?
+ if raise
+ record.save!(:validate => validate)
+ else
+ return unless record.save(:validate => validate)
+ end
+ end
if options[:insert_sql]
owner.connection.insert(interpolate(options[:insert_sql], record))
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb
index 7172e89a05..50ee60284c 100644
--- a/activerecord/lib/active_record/associations/has_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_association.rb
@@ -7,9 +7,14 @@ module ActiveRecord
# is provided by its child HasManyThroughAssociation.
class HasManyAssociation < CollectionAssociation #:nodoc:
- def insert_record(record, validate = true)
+ def insert_record(record, validate = true, raise = false)
set_owner_attributes(record)
- record.save(:validate => validate)
+
+ if raise
+ record.save!(:validate => validate)
+ else
+ record.save(:validate => validate)
+ end
end
private
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index 7708228d23..280688be52 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -33,9 +33,16 @@ module ActiveRecord
super
end
- def insert_record(record, validate = true)
+ def insert_record(record, validate = true, raise = false)
ensure_not_nested
- return if record.new_record? && !record.save(:validate => validate)
+
+ if record.new_record?
+ if raise
+ record.save!(:validate => validate)
+ else
+ return unless record.save(:validate => validate)
+ end
+ end
through_record(record).save!
update_counter(1)