更新子项时Rails嵌套模型表单错误

时间:2014-12-12 10:23:02

标签: ruby-on-rails ruby-on-rails-4

我有Person模型和Business模型have_many contacts, as:contactable

我不确定更新嵌套模型的正确方法,但我所做的如下:

我的params哈希如下:

{"person"=>
  {"name"=>"updated name",
   .......
   "contacts_attributes"=>
    {"0"=>{"contact_type"=>"web", "contact_sub_type"=>"main", "address"=>"http:www.example.com/changed", "id"=>"2"},
     "1"=>{"contact_type"=>"twitter", "contact_sub_type"=>"main", "address"=>"changedtwerson", "id"=>"4"},
"2"=> {contact_type: "facebook", contact_sub_type: "main" , id: "3" },
"3"=> {contact_type: "email", contact_sub_type: "main",id: "1" }
}},
     "submit"=>"save",
     "id"=>"1",
     "controller"=>"persons",
     "action"=>"update"}

在模型中,我已经有3 person.contacts Contact.contact_type" web"," facebook"和" twitter" contact_sub_type对应上面的输入。

在联系模式中,我有validates_uniqueness_of :contact_type, scope: [:contact_sub_type, :contactable_id ]

因为如果地址为空,我不想将联系人加载到方法中包含的Person / Business对象,以将强params代码设置为destroy_all没有地址的记录:

def person_params
    contact_list = params[:person][:contacts_attributes].delete_if { |key, value| value[:address].blank? } if params[:person].present? && params[:person][:contacts_attributes].present?
    cl_ary = []
    contact_list.values.each { |v| cl_ary << v[:id] }
    @person.contacts.where.not(id: cl_ary).destroy_all if @person && @person.contacts

    params.require(:person).permit(:name, ......
                    contacts_attributes: [:id, :address, :contact_type, :contact_sub_type]) unless params[:person].nil?
end

我打电话的时候 @person = Person.find(id:params [:id]) @ person.update person_params

我返回的值为false,@ person无效:contact_type=>["has already been taken"]

更新后@person.contacts给我以下内容(我应该通过唯一验证)

[#<Contact id: 4, contact_type: "twitter", contact_sub_type: "main", address: "changedtwerson", contactable_id: 1, contactable_type: "Person", created_at: "2014-12-12 10:09:15", updated_at: "2014-12-12 10:09:24">, #<Contact id: 2, contact_type: "web", contact_sub_type: "main", address: "http:www.example.com/changed", contactable_id: 1, contactable_type: "Person", created_at: "2014-12-12 10:09:15", updated_at: "2014-12-12 10:09:24">]

因此我有两个问题:

  1. 我在这里有一个有效的方法,我错过了什么,有更好的方法吗?
  2. 如何进一步了解验证并找出验证在视觉上看起来不正确的原因?

1 个答案:

答案 0 :(得分:1)

回答问题1:这不是一种有效的方法。

通过添加:

重构Person

accepts_nested_attributes_for :contacts, :allow_destroy => true, :reject_if => proc {|attrs| attrs[:address].blank?}

并从person_params方法删除:

contact_list = params[:person][:contacts_attributes].delete_if { |key, value| value[:address].blank? } if params[:person].present? && params[:person][:contacts_attributes].present? cl_ary = [] contact_list.values.each { |v| cl_ary << v[:id] } @person.contacts.where.not(id: cl_ary).destroy_all if @person && @person.contacts

同时将验证器更改为:

validates_uniqueness_of :contact_type, scope: [:contact_sub_type, :contactable_id, :contactable_type] 

防止人/商业竞争条件。

重构update行动:

@person = Person.find(id: params[:id])
@person.attributes = person_params 
@person.contacts.select {|x| x.address.blank?}.each(&:mark_for_destruction)
@person.save