在父项创建上创建嵌套记录
问题描述:
我有一个UserReport模型连接用户模型和报告模型。 (有很多通过关联)。在父项创建上创建嵌套记录
我有另一种叫做Comment的模型属于UserReport。 (有很多关联) 当创建一个报告时,我需要为所有用户创建一个UserReport,并提供一个默认评论。
我的问题是如何做到这一点,将回滚报表创建,如果任何一个子记录保存失败。
我的目标是确保数据库不会停留在包含状态。
有什么建议吗?
答
如果您的模型是save
,则整个过程将被包装在一个事务中,如果保存失败(由于验证,回调等)将会回退。因此,如果您先在内存中构建整个对象树,然后尝试报告,则如果出现任何故障,则不会保存任何对象。
这里有一个如何做到这一点的例子:
# in report.rb
class Report < ActiveRecord::Base
validates_associated :user_reports
end
# in user_report.rb
class UserReport < ActiveRecord::Base
validates_associated :comments
end
# in your controller or wherever you're doing this
report = Report.new
User.pluck(:id).each{ |user_id| report.user_reports.build(user_id: user_id) }
report.user_reports.each{ |user_report| user_report.comments.build }
report.save # will always save either everything or nothing, no inconsistencies
注意使用#new
和#build
以避免犯任何东西,直到最后一行。模型中的validates_associated
行会导致子对象上的任何验证错误传播到父对象,即使父对象本身通过验证也无法保存它。
答
你想要一个叫做事务的东西。该代码会看起来像
begin
Report.transaction do
# create report like Report.create! or something
# create comments like Comment.create! or something
end
rescue
# there was an error
end
的事务中,如果发生错误时将数据库恢复到它是整个交易中开始了。在救援中,您可以处理任何抛出的错误。