TL;博士
这看起来应该很简单。我想设置#accepts_nested_attributes_for,这样当我使用为子类设置的任何非空参数保存父类时,它会删除在参数中没有被其id直接引用的任何其他子类。
出于某种原因,我真的很难找到一种明智的方式来做到这一点。
就是这样。
更长的版本
我有一个模型,承诺:
class Pledge < ActiveRecord::Base
has_many :companies, dependent: :destroy
accepts_nested_attributes_for :companies
# Other stuff
end
以及相应的公司模型:
class Company < ActiveRecord::Base
belongs_to :pledge
end
假设我已经将 company_1 (id: 1, name: company_1) 保存在承诺_a 上,然后我调用pledge_.update(params)
,其中params
任何一个都没有引用公司 id,因此:
{
"someotherval"=>"5",
"id"=>"10",
"companies_attributes"=>
{
"0"=>
{
"name"=>"company_2"
}
}
}
或(与上述完全相同,但是)为相关公司提供不同的 ID:
{
"someotherval"=>"5",
"id"=>"10",
"companies_attributes"=>
{
"0"=>
{
"id"=>"2"
"name"=>"company_2"
}
}
}
指示 Rails 删除任何未包含在参数中的公司的最简单方法是什么,即每次我在嵌套参数中使用任何现有公司调用 #update 时创建一个新集合?
我已经尝试了很多东西:
在 Pledge 上使用 before_save 挂钩删除公司 - 这似乎在保存公司后删除它们,所以我总是以无公司的承诺结束
通过将 :reject_if 块添加到 accept_nested_attributes_for 一行然后将其用于 destroy_all_companies after_save 挂钩来构建公司数组 - 这不起作用,因为在某些时候 Rails 似乎重新初始化了承诺,所以到那时我们上钩了,数组消失了
在我调用#update 删除公司之前在控制器中编写一些代码 - 这是我已经减少到的黑客,但它是可怕的。首先,如果我传递不包含任何嵌套公司参数的参数,我并不总是想删除公司。其次,我必须检查参数并删除任何非空的公司#id 值,否则 Rails 在找不到相关公司时会爆炸。第三,如果验证失败并且 Pledge 没有更新,我现在已经删除了我不想删除的所有公司。
必须有一个更理智的方法来做到这一点......对吧?