在父创建上创建嵌套记录

时间:2013-11-22 21:16:59

标签: ruby-on-rails activerecord

我有一个UserReport模型,用于连接User模型和Report模型。 (通过协会有很多)。

我有另一个名为Comment的模型属于UserReport。 (有很多协会) 创建报告时,我需要为具有一个默认注释的所有用户创建一个UserReport。

我的问题是,如果任何一个子记录无法保存,将以回滚报告创建的方式执行此操作。

我的目标是确保数据库不会处于内置状态。

有什么建议吗?

2 个答案:

答案 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行会导致子对象上的任何验证错误传播到父对象,即使父对象本身通过验证也无法保存。

相关问题