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