我有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">]
因此我有两个问题:
答案 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