2013-11-22 3 views
0

У меня есть модель UserReport, которая соединяет модель пользователя и модель отчета. (имеет много связей).Создание вложенных записей в родительском создании

У меня есть еще одна модель под названием Комментарий, принадлежащая UserReport. (имеет много ассоциаций) Когда создается отчет, мне нужно создать UserReport для всех пользователей с одним комментарием по умолчанию.

Мой вопрос заключается в том, как сделать это таким образом, чтобы откат создания отчета, если какая-либо из дочерних записей не удалось сохранить.

Моя цель - обеспечить, чтобы БД не оставалась в состоятельном состоянии.

Любые предложения?

ответ

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 в моделях вызывают ошибки проверки дочерних объектов для распространения на родительский объект, что предотвращает его сохранение, даже если сам родительский объект проходит проверку.

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 

Внутри транзакции, если выдается ошибка базы данных вернулась к тому, что это было до того, как вся сделка была начата. В спасении вы можете обрабатывать любые ошибки, которые были выброшены.

Смежные вопросы