1

我有一个有多个孩子的父母。我想要这样当我提交表单时,在父模型中生成一个父模型,并在子模型中创建多个记录,每个子模型一个。当我尝试提交时,我收到以下错误:

 ActiveRecord::AssociationTypeMismatch in ParentsController#create

   Child(#) expected, got Array(#)

当我取消注释 Accepts_nested_attributes_for :children 并将 f.fields_for :children 更改为 f.fields_for :children_attributes 时,我得到一个不同的错误:

  TypeError in ParentsController#create

    can't convert Symbol into Integer

我不知道该怎么做。我已经检查了嵌套模型表单 railscasts,但他们正在处理在表单内生成子字段,而我从 railscasts 中学到的东西似乎不起作用。我很漂亮,我的 builder.text_field :cname 在我的表单中是错误的,但我不知道正确的方法。

我的代码:

父.rb

class Parent < ActiveRecord::Base
  has_many :children
  #accepts_nested_attributes_for :children
  attr_protected :id

子.rb

class Child < ActiveRecord::Base
  belongs_to :parent
  attr_protected :id

_form.html.erb

<%= form_for @parent, :url => { :action => "create" } do |f| %>
  <%= f.text_field :pname %>
  <%= f.fields_for :children do |builder| %>
    <%= builder.text_field :cname %>
    <%= builder.text_field :cname %>
    <%= builder.text_field :cname %>
  <% end %>
  <%= f.submit %>
<% end %>

参数内容:

{"utf8"=>"✓",
 "authenticity_token"=>"FQQ1KdNnxLXolfes9IGiO+aKHJaPCH+2ltDdA0TwF7w=",
 "parent"=>{"pname"=>"Heman",
 "child"=>{"cname"=>""}},
 "commit"=>"Create"}
4

1 回答 1

4

这里的问题是,在 HTML 中为孩子们生成的表单在 params 哈希(使用对)中使用相同的“位置”(相同的键/值params[:parent][:child][:cname]对)。这就是为什么在 Params 哈希中的“子”节点中只有一个参数“名称”。

为避免这种情况,您可以使用数组作为输入名称:

<input type="text" name="child[][cname]" />
<input type="text" name="child[][cname]" />

提交时,参数将如下所示:

params: {
  child: [ { cname: 'blabla' }, { cname: 'bonjour' } ]
}

要获得所需的结果,在您的情况下

<%= form_for @parent, :url => { :action => "create" } do |f| %>
  <%= f.text_field :pname %>

  <%= text_field_tag "parent[children][][cname]" %>
  <%= text_field_tag "parent[children][][cname]" %>
  <%= text_field_tag "parent[children][][cname]" %>

  <%= f.submit %>
<% end %>

应该产生这样的东西:

{
  "utf8"=>"✓",
  "authenticity_token"=>"FQQ1KdNnxLXolfes9IGiO+aKHJaPCH+2ltDdA0TwF7w=",
  "parent"=> { 
    "pname"=>"Heman",
    "children"=> [
      { "cname"=>"SisiSenior" },
      { "cname"=>"Bonjor" },
      { "cname"=>"Blabla" }
    ]
  },
  "commit"=>"Create"}

所以在你的控制器中,你可以使用这样的东西:

#ParentsController
def create
  children_attributes = params[:parent].delete(:children) # takes off the attributes of the children
  @parent = Parent.create(params[:parent])

  children_attributes.each do |child_attributes|
    child = @parent.children.create(child_attributes)
  end
end
于 2013-07-03T18:15:56.897 回答