仅在成功保存父对象时才将更改保存到has_many关联?
假设每个Project
都有很多Tasks
。
如果我做
some_project.tasks = list_of_tasks some_project.save
即使保存失败,项目的任务也会更新。 如果list_of_tasks
包含新记录,即使保存失败,项目的任务也会被删除 ! 哇!
如果保存失败,项目应该具有与我开始搞乱之前相同的任务。 我如何得到这种行为,为什么不是默认行为?
将语句包含在事务中:
Project.transaction do p.tasks = task_list p.save! end
save!
方法在出错时抛出exception,从而回滚对任务列表所做的任何更改。
如果您想更深入地了解该主题,可以阅读文档 。
我相信accepts_nested_attributes_for()将提供您想要的行为:
class Project < ActiveRecord::Base accepts_nested_attributes_for :tasks end
这应该包装事务中的所有内容。 然后,您需要构建相应填充任务的表单。 调用Project模型中的tasks_attributes
方法而不是tasks
方法。 有关更多信息,请参阅API 。
您可能会发现AutosaveAssociationfunction可以满足您的需求。
class Project < ActiveRecord::Base has_many :tasks, :autosave => true end
这应该自动将保存包装在事务中。
在调用#save
之前,您可以询问some_project#valid?
。 如果由于some_project
是无效记录而导致保存失败,但这不是一个全面的解决方案,那么这有助于解决问题。
至于Rails的默认行为,它是有道理的。 说some_project.tasks = list_of_tasks
就像是说“从some_project中删除所有现有任务并分配这些新任务”。 您将删除对现有关联数组的引用并分配一个全新的关联数组。 这由DB中的ActiveRecord反映出来。