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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:36:22  来源:igfitidea点击:

Rails 4 Update Nested Attributes

ruby-on-railsrubyactiverecord

提问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.

在上面的代码中,您需要添加checkboxlabel来传递_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 :personPet模型中没有关联,请将其添加到模型中

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