我有一个UserReport模型,用于连接User模型和Report模型。 (通过协会有很多)。
我有另一个名为Comment的模型属于UserReport。 (有很多协会) 创建报告时,我需要为具有一个默认注释的所有用户创建一个UserReport。
我的问题是,如果任何一个子记录无法保存,将以回滚报告创建的方式执行此操作。
我的目标是确保数据库不会处于内置状态。
有什么建议吗?
答案 0 :(得分:2)
你想要一种叫做交易的东西。代码看起来像
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
在事务内部,如果抛出错误,数据库将恢复到整个事务开始之前的状态。在救援中,您可以处理任何抛出的错误。
答案 1 :(得分:0)
当您save
模型时,整个流程将包含在事务中,如果保存失败(由于验证,回调等),将回滚该事务。因此,如果您首先在内存中构建整个对象树,然后尝试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
行会导致子对象上的任何验证错误传播到父对象,即使父对象本身通过验证也无法保存。