Ruby-on-rails Rails 4 更新嵌套属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23492873/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails 4 Update Nested Attributes
提问by Kush Jain
Updating Nested Attributes append instead of updating in has many relationships I am trying to use Rails 4 Update_attributes
更新嵌套属性追加而不是更新有很多关系我正在尝试使用 Rails 4 Update_attributes
Class Person <ActiveRecord::Base
has_many :pets
accepts_nested_attributes_for :pets
end
Class Pet < ActiveRecord::Base
belongs_to :person
end
In my controller I am recieveing the params as {id: 23, house_no:'22A', pets: [{name:'jeffy', type:'dog'}, {name:'sharky', type:'fish'}]}
在我的控制器中,我收到的参数为 {id: 23, house_no:'22A', pets: [{name:'jeffy', type:'dog'}, {name:'sharky', type:'fish'} ]}
and my update method is
我的更新方法是
def update
@Person = Person.find(params[:id])
if @Person.update(person_params)
@Person.save
render 'persons/create', status 200
else
render 'persons/create', status 400
end
end
private
def person_params
person_params = params.permit(:house_no)
person_params.merge! ({pets_attributes: params[:pets]}) if params[:pets].present?
person_params
end
Now when I update it and if the person already has a pet then the new pets gets appended instead of getting updated eg if a person with id 1 has 1 pet named "Tiger" and I update that person with 2 pets named "Shasha" and "Monti" then the person record has 3 pets (Tiger, Shasha and Monti) instead of updating it to 2 (Shasha and Monti)
现在当我更新它并且如果这个人已经有一只宠物,那么新的宠物会被附加而不是被更新,例如,如果一个 id 1 的人有 1 只名为“Tiger”的宠物,我用 2 只名为“Shasha”的宠物更新了那个人,并且“Monti”然后个人记录有 3 只宠物(Tiger、Shasha 和 Monti)而不是将其更新为 2(Shasha 和 Monti)
采纳答案by Suchit Puri
see the manual:
看手册:
http://api.rubyonrails.org/v4.0.1/classes/ActiveRecord/NestedAttributes/ClassMethods.html
http://api.rubyonrails.org/v4.0.1/classes/ActiveRecord/NestedAttributes/ClassMethods.html
you need to send in your attributes like pets_attributes:[{name:'jeffy', type:'dog'}, {name:'sharky', type:'fish'}]
你需要发送你的属性,比如 pets_attributes:[{name:'jeffy', type:'dog'}, {name:'sharky', type:'fish'}]
and it should work fine.
它应该可以正常工作。
Please read
请阅读
You can now set or update attributes on the associated posts through an attribute hash for a member: include the key :posts_attributes with an array of hashes of post attributes as a value.For each hash that does not have an id key a new record will be instantiated, unless the hash also contains a _destroy key that evaluates to true.
您现在可以通过成员的属性散列设置或更新相关帖子的属性:包括键 :posts_attributes 和一个帖子属性的散列数组作为值。对于每个没有 id 键的散列,新记录将被实例化,除非散列还包含评估为真的 _destroy 键。
回答by Kirti Thorat
Update the Personmodel as below:
更新Person模型如下:
class Person < ActiveRecord::Base ## NOTE: class (c lowercase) and NOT Class
has_many :pets
accepts_nested_attributes_for :pets, allow_destroy: true ## Added allow_destroy
end
In order to destroy the associated model i.e., Petthrough the attributes hash, you have to enable it first using the :allow_destroyoption.
为了销毁关联的模型,即Pet通过属性散列,您必须首先使用该:allow_destroy选项启用它。
Then, from your view, you will need to pass the _destroyattribute for the pets that you would like to be removed.
然后,从您的角度来看,您需要传递_destroy您想要移除的宠物的属性。
Since, you haven't shared the view specific code. Following is an example of how it should be implemented in your view. Change it according to your requirement:
因为,您还没有共享视图特定的代码。下面是一个示例,说明它应该如何在您的视图中实现。根据您的要求更改它:
<%= form_for @person do |f| %>
<%## .. %>
<%= f.fields_for :pets do |builder| %>
<%## .. %>
<%= builder.check_box :_destroy %>
<%= builder.label :_destroy, "Remove Pet" %>
<% end %>
<% end %>
In the above code, you would need to add the checkboxand labelfor passing _destroyvalue.
在上面的代码中,您需要添加checkbox和label来传递_destroy值。
After this, update the person_paramsmethod in your controller as below:
在此之后,更新person_params控制器中的方法如下:
def person_params
params.require(:person).permit(:house_no, pets_attributes: [:id, :name, :type, :person_id, :_destroy])
end
NOTE:
笔记:
You should notbe defining instance variableswith capitalizedname. Capitalized names are used for declaring Constantsin Ruby.
您不应该instance variables使用大写名称进行定义。大写名称用于声明Constantsin Ruby。
def update
@person = Person.find(params[:id])
if @person.update(person_params)
@person.save
render 'persons/create', status 200
else
render 'persons/create', status 400
end
end
回答by Panos Malliakoudis
Can you try adding the :idattribute to the :pets_attributesarray in person_params?
您可以尝试将:id属性添加到:pets_attributes数组中person_params吗?
You need to permit the id attribute.
您需要允许 id 属性。
回答by faisal bhatti
You need to edit you params with pets_attributes
您需要使用 pets_attributes 编辑您的参数
Also need to add :id paramter in the pet objects.
还需要在宠物对象中添加 :id 参数。
回答by Lenin Raj Rajasekaran
Probably 1. you would want to assign pets separately,
可能 1. 你想单独分配宠物,
@Person.pets = Pets.find(params[:pets])
Or 2. clear the pets before saving Person.
或 2. 在拯救人之前清除宠物。
@Person.pets.destroy
回答by Pavan
Try changing your person_paramsas
尝试改变你的person_params作为
def person_params
person_params = params.require(:person).permit(:house_no ,pets_attributes: [:name,:type])
end
And remove @person.savefrom the update method.You don't need it.And also use !for update
并@person.save从更新方法中删除。你不需要它。也!用于update
def update
@Person = Person.find(params[:id])
if @Person.update!(person_params)
render 'persons/create', status 200
else
render 'persons/create', status 400
end
end
Update
更新
And also,as i can see there is no belongs_to :personassociation in Petmodel,Add it in the model
而且,正如我所看到的belongs_to :person,Pet模型中没有关联,请将其添加到模型中
Class Pet < ActiveRecord::Base
belongs_to :person
end
And now permit the person_idattribute by adding it in the params
现在person_id通过将其添加到params
def person_params
person_params = params.require(:person).permit(:house_no,pets_attributes: [:name,:type,:person_id])
end

