开发者

save an active records array

I have an arra开发者_开发问答y like this

a = []

a << B.new(:name => "c")
a << B.new(:name => "s")
a << B.new(:name => "e")
a << B.new(:name => "t")

How i can save it at once?


B.transaction do
  a.each(&:save!)
end

This will create a transaction that loops through each element of the array and calls element.save on it.

You can read about ActiveRecord Transactions and the each method in the Rails and Ruby APIs.


a.each(&:save)

This will call B#save on each item in the array.


So I think we need a middle ground to Alexey's raising exceptions and aborting the transaction and Jordan's one-liner solution. May I propose:

B.transaction do
  success = a.map(&:save)
  unless success.all?
    errored = a.select{|b| !b.errors.blank?}
    # do something with the errored values
    raise ActiveRecord::Rollback
  end
end

This will give you a bit of both worlds: a transaction with rollback, knowledge of which records failed and even gives you access to the validation errors therein.


Wrapping save in transaction will not be enough: if a validation is not passed, there will be no exception raised and no rollback triggered.

I can suggest this:

B.transaction do
  a.each do |o|
    raise ActiveRecord::Rollback unless o.save
  end
end

Just doing B.transaction do a.each(&:save!) end is not an option either, because the transaction block will not rescue any exception other than ActiveRecord::Rollback, and the application would crash on failed validation.

I do not know how to check afterwards if the records have been saved.


Update. As someone has downrated my answer, i assume that the person was looking for a cut-and-paste solution :), so here is some (ugly :)) way to process fail/success value:

save_failed = nil
B.transaction do
  a.each do |o|
    unless o.save
      save_failed = true
      raise ActiveRecord::Rollback
    end
  end
end
if save_failed
  # ...
else
  # ...
end


I know this is an old question but I'm suprised no one thought of this:

B.transaction do
  broken = a.reject { |o| o.save }
  raise ActiveRecord::Rollback if broken.present?
end

if broken.present?
  # error message
end


In case you're looking for more efficient solution than save each row in the loop please look my answer here Ruby on Rails - Import Data from a CSV file

I'm suggesting to use gem activerecord-import there.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜