在父项创建上创建嵌套记录

问题描述:

我有一个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 

的事务中,如果发生错误时将数据库恢复到它是整个交易中开始了。在救援中,您可以处理任何抛出的错误。