我有一个像这样的数组
a = []
a << B.new(:name => "c")
a << B.new(:name => "s")
a << B.new(:name => "e")
a << B.new(:name => "t")
我怎样才能立刻保存它?
答案 0 :(得分:45)
B.transaction do
a.each(&:save!)
end
这将创建一个循环遍历数组的每个元素并在其上调用element.save的事务。
您可以在Rails和Ruby API中阅读ActiveRecord Transactions和the each method。
答案 1 :(得分:25)
a.each(&:save)
这会在数组中的每个项目上调用B#save
。
答案 2 :(得分:11)
所以我认为我们需要一个中间立场,让Alexey提高例外并中止交易以及Jordan的单线解决方案。我可以提议:
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
这将为您提供两个方面:具有回滚的事务,知道哪些记录失败,甚至可以让您访问其中的验证错误。
答案 3 :(得分:2)
我知道这是一个老问题,但我很惊讶没有人想到这个:
B.transaction do
broken = a.reject { |o| o.save }
raise ActiveRecord::Rollback if broken.present?
end
if broken.present?
# error message
end
答案 4 :(得分:0)
在事务中包装save
是不够的:如果未通过验证,则不会引发异常并且不会触发回滚。
我可以建议:
B.transaction do
a.each do |o|
raise ActiveRecord::Rollback unless o.save
end
end
只是做B.transaction do a.each(&:save!) end
也不是一个选项,因为事务块不会解除除ActiveRecord::Rollback
以外的任何异常,并且应用程序会在验证失败时崩溃。
如果记录已保存,我不知道如何检查。
更新。由于有人低估了我的答案,我认为这个人正在寻找一个剪切和粘贴的解决方案:),所以这里有一些(丑陋的))处理失败/成功价值的方法:
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
答案 5 :(得分:0)
如果您正在寻找比保存循环中每一行更有效的解决方案,请在此处查看我的答案Ruby on Rails - Import Data from a CSV file
我建议在那里使用gem activerecord-import
。