Skip to content

Commit

Permalink
Only save the record once when calling create! on a collection associ…
Browse files Browse the repository at this point in the history
…ation. Fixes #1360.
  • Loading branch information
jonleighton committed May 31, 2011
1 parent 842043e commit 64d7348
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 25 deletions.
Expand Up @@ -104,26 +104,11 @@ def build(attributes = {}, options = {}, &block)
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.
Expand Down Expand Up @@ -422,8 +407,25 @@ def merge_target_lists(persisted, memory)
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

Expand Down
Expand Up @@ -9,8 +9,14 @@ def initialize(owner, reflection)
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))
Expand Down
Expand Up @@ -7,9 +7,14 @@ module Associations
# 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
Expand Down
Expand Up @@ -33,9 +33,16 @@ def concat(*records)
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)
Expand Down

0 comments on commit 64d7348

Please sign in to comment.