我可以在rails中使用accepts_nested_attributes_for删除缺少的关联吗?

时间:2017-07-19 18:00:56

标签: ruby-on-rails accepts-nested-attributes

TL; DR

这看起来应该非常简单。我想设置#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

假设我已经在pledge_a上保存了company_1(id:1,name:company_1),然后我致电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时创建一个新组合? / p>

我尝试过很多事情:

在Pledge上使用before_save挂钩删除公司 - 在公司被保存之后,这似乎删除了他们所以我总是以无公司承诺结束

通过将:reject_if块添加到一行的accepts_nested_attributes_然后将其用于destroy_all_companies after_save hook来构建公司数组 - 这没有用,因为在某些时候Rails似乎重新初始化了承诺,所以当我们碰到钩子时,阵列已经消失了

在我调用#update删除公司之前在控制器中编写一些代码 - 这是我被贬低的黑客,但它是可怕的。首先,如果我通过不包含任何嵌套公司参数的参数,我总是不想删除这些公司。其次,我必须通过参数并删除任何非空的公司#id值,否则当Rails无法找到有问题的公司时会爆炸。第三,如果验证失败且承诺没有更新,我现在已经删除了所有公司。

必须有一个更健全的方法来做到这一点......对吗?

1 个答案:

答案 0 :(得分:1)

给出您要销毁的公司的列表,例如:

companies_to_destroy = @pledge.companies.reject do |company|
  pledge_params[:companies_attributes]
    .map { |attrs| attrs[:id] }
    .include? company.id
end

正如@gabrielhilal的评论所建议的那样,您可以在allow_destroy: true中使用accepts_nested_attributes_for,然后将每个要销毁的公司添加到companies_attributes数组{ id: 'x', _destroy: '1' }中。

或者,您可以致电您要销毁的公司mark_for_destruction

在任何一种情况下,当您致电保证书时,销毁公司都将被销毁。