保存活动记录数组
我有这样的数组
a = [] a < "c") a < "s") a < "e") a < "t")
我怎么能立刻保存它?
a.each(&:save)
这将在arrays中的每个项目上调用B#save
。
B.transaction do a.each(&:save!) end
这将创建一个循环遍历数组的每个元素并在其上调用element.save的事务。
您可以阅读有关ActiveRecord事务以及Rails和Ruby API中的每个方法的信息。
所以我认为我们需要一个中间立场,让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
这将为您提供两个方面:具有回滚的事务,知道哪些记录失败,甚至可以让您访问其中的validation错误。
我知道这是一个古老的问题,但我很惊讶没有人想到这个:
B.transaction do broken = a.reject { |o| o.save } raise ActiveRecord::Rollback if broken.present? end if broken.present? # error message end
在事务中包装save
是不够的:如果未传递validation,则不会引发exception并且不会触发回滚。
我可以建议一下:
B.transaction do a.each do |o| raise ActiveRecord::Rollback unless o.save end end
只做B.transaction do a.each(&:save!) end
也不是一个选项,因为事务块不会拯救除ActiveRecord::Rollback
之外的任何exception,并且应用程序在validation失败时会崩溃。
如果记录已保存,我不知道如何检查。
更新 。 由于有人低估了我的答案,我认为这个人正在寻找一个剪切和粘贴的解决方案:),所以这里有一些(丑陋的:))处理失败/成功价值的方法:
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
如果您正在寻找比保存循环中每一行更有效的解决方案,请在此处查看我的答案Ruby on Rails – 从CSV文件导入数据
我建议在那里使用gem activerecord-import
。