【问题标题】:Ruby on Rails creating multiple children in one parent formRuby on Rails 在一个父窗体中创建多个子窗体
【发布时间】:2013-07-03 17:48:11
【问题描述】:

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

 ActiveRecord::AssociationTypeMismatch in ParentsController#create

   Child(#) expected, got Array(#)

当我取消注释 accept_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

child.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"}

【问题讨论】:

  • 您可以在提交表单时发布包含儿童属性的params 吗?我很确定你只需要循环 params[:children] 因为你的错误日志告诉我们它是一个数组
  • @MrYoshiji 你可能会再次来救我。我已经用参数更新了我的问题。只有一个孩子出现,而且没有显示任何名字。
  • 啊,我认得这个...给我一分钟,我发布一个答案,而你可以看看这个非常相似的问题:stackoverflow.com/questions/16919711/…

标签: ruby-on-rails forms parent-child fields-for


【解决方案1】:

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

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

<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

【讨论】:

  • 圣斗士伴侣。你是一个救生员。非常感谢。当然,愿你的剑保持锋利,让你的战马快点。
  • 对此很抱歉,但我认为这太简单了,不能成为一个新问题。如果名称不是空白,有没有办法让它只创建记录?我认为只使用 if #something != nil child=@parent.children.create(child_attributes) end 是可行的,但我不知道该放什么而不是 #something。
  • 没关系,我想通了。我用 child_attributes["name"] != "" 替换了 #something != nil
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 2014-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多