Rails 4更新嵌套属性

时间:2014-05-06 11:00:46

标签: ruby ruby-on-rails-3 activerecord 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

在我的控制器中,我正在接受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

现在我更新它 如果这个人已经有宠物了 然后新的宠物被附加而不是更新 例如,如果身份1的人有1只名为“老虎”的宠物 我用2只名为“Shasha”和“Monti”的宠物更新了那个人,然后这个人记录有3只宠物(Tiger,Shasha和Monti),而不是将它更新为2(Shasha和Monti)

6 个答案:

答案 0 :(得分: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键的每个哈希a除非哈希还包含一个计算结果为true的_destroy键,否则将实例化新记录。

答案 1 :(得分:13)

更新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

为了通过属性哈希销毁关联模型,即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 %>

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

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

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

注意:

不应使用大写名称定义instance variables。大写名称用于在Constants中声明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  

答案 2 :(得分:12)

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

您需要允许id属性。

答案 3 :(得分:1)

可能1.你想分开分配宠物,

@Person.pets = Pets.find(params[:pets])

或2.在保存人员之前清除宠物。

@Person.pets.destroy

答案 4 :(得分:1)

尝试将person_params更改为

def person_params
  person_params = params.require(:person).permit(:house_no ,pets_attributes: [:name,:type])
end

从更新方法中移除@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

<强>更新

另外,我可以看到belongs_to :person模型中没有Pet关联,在模型中添加

Class Pet < ActiveRecord::Base

belongs_to :person

end

现在允许在person_id

中添加params属性
def person_params
  person_params = params.require(:person).permit(:house_no,pets_attributes: [:name,:type,:person_id])
end

答案 5 :(得分:1)

您需要使用pets_attributes

编辑params

还需要在宠物对象中添加:id参数。