Rails 4更新嵌套属性

Kus*_*ain 23 ruby activerecord ruby-on-rails-3 ruby-on-rails-4

更新嵌套属性追加而不是更新有许多关系我试图使用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
Run Code Online (Sandbox Code Playgroud)

在我的控制器中,我正在接受params为{id:23,house_no:'22A',宠物:[{name:'jeffy',type:'dog'},{name:'sharky',type:'fish'} ]}

我的更新方法是

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
Run Code Online (Sandbox Code Playgroud)

现在,当我更新它并且如果该人已经有宠物时,则新宠物被附加而不是更新,例如,如果id为1的人有1只名为"Tiger"的宠物并且我用2只名为"Shasha"的宠物更新该人"Monti"然后这个人的记录有3只宠物(Tiger,Shasha和Monti)而不是更新为2(Shasha和Monti)

小智 15

看手册:

http://api.rubyonrails.org/v4.0.1/classes/ActiveRecord/NestedAttributes/ClassMethods.html

你需要发送你的属性,如 pets_attributes:[{name:'jeffy', type:'dog'}, {name:'sharky', type:'fish'}]

它应该工作正常.

请阅读

您现在可以通过成员的属性哈希在关联的帖子上设置或更新属性:包括键:posts_attributes,其中包含一系列post属性的哈希作为值.对于没有id键的每个哈希,新记录将实例化,除非哈希还包含一个计算结果为true的_destroy键.

  • 这只有在您不小心离开`:id`参数时才有效.为了避免重复在`pets_attributes`中放置`:id` (6认同)
  • 同意pets_attributes但还需要在pets对象中添加:id (2认同)

Kir*_*rat 14

更新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
Run Code Online (Sandbox Code Playgroud)

为了破坏关联的模型,即Pet通过属性哈希,您必须首先使用该:allow_destroy选项启用它.

然后,从您的视图中,您需要传递_destroy您想要删除的宠物的属性.

因为,您还没有共享视图特定代码.以下是如何在您的视图中实现它的示例.根据您的要求更改:

<%= form_for @person do |f| %>
  <%## .. %>  
  <%= f.fields_for :pets do |builder| %>
    <%## .. %>    
    <%= builder.check_box :_destroy %>
    <%= builder.label :_destroy, "Remove Pet" %>
  <% end %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,您需要添加checkboxlabel传递_destroy值.

在此之后,更新person_params控制器中的方法,如下所示:

def person_params
  params.require(:person).permit(:house_no, pets_attributes: [:id, :name, :type, :person_id, :_destroy])
end 
Run Code Online (Sandbox Code Playgroud)

注意:

应该instance variables使用大写名称进行定义.大写名称用于声明ConstantsRuby.

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  
Run Code Online (Sandbox Code Playgroud)


小智 13

你可以尝试将:id属性添加到:pets_attributes 数组中person_params吗?

您需要允许id属性.

  • @AkashAggarwal你怎么知道你要破坏哪条记录?你需要一个`id`它.每个人都提到`_destroy`但是OP询问如何**更新**,而不是销毁.如果你想修复破坏,那么你肯定需要添加`_destroy`,但是为了更新,你需要一个`id`. (4认同)
  • 这是唯一真正正确的答案.`:id`至关重要."破坏"解释也是有道理的,但这个实际回答了OP的问题. (3认同)