具有多个嵌套模型的Rails表单会导致无线电组出现问题

ror*_*ryf 5 ruby-on-rails actionview radio-button

我遇到了包含单选按钮的嵌套模型表单的问题,当我有多个模型时,所有单选按钮都被视为在同一组中.

我的模型包含一个像这样的has_many关系:

class Order < ActiveRecord::Base
    has_many :order_items
    accepts_nested_attributes_for :order_items
end

Class OrderItem < ActiveRecord::Base
    belongs_to :order
end
Run Code Online (Sandbox Code Playgroud)

然后我有一个部分使用创建OrderItem模型表单

<% fields_for "order[order_items_attributes][]", order_item do |f| %>
Run Code Online (Sandbox Code Playgroud)

这个表单中包含一组在for循环中创建的单选按钮

radio_button_tag "order[order_items_attributes][][colour_id]", "#{colour.id}"
Run Code Online (Sandbox Code Playgroud)

当只有一个孩子时,这可以正常工作,但是当我插入多个孩子时,所有单选按钮都属于同一个组,因为它们都具有相同的属性name="order[order_items_attributes][][colour_id]".这一切都在一个新的模型表单上,所以我不能使用数组索引(name="order[order_items_attributes][0][colour_id]"),因为Rails给出了expected Hash (got Array) for param 'order_items_attributes' 我最后一部分错误的错误,错误是因为我混合了索引和非索引的名称属性.添加索引值是解决这个问题的关键.

以下是params[:order]仅存在一个嵌套模型时哈希的内容:

{"order_items_attributes"=>
  [{"size"=>"Small",
    "colour_id"=>"4"],
 "first_name"=>"sdf",
 "last_name"=>"sdf",
 "email"=>"sdfg@sgf.com"}
Run Code Online (Sandbox Code Playgroud)

当存在两个嵌套模型时:

{"order_items_attributes"=>
  [{"size"=>"Small",
    "colour_id"=>"4"},
   {"size"=>"Small"}],
 "first_name"=>"sdf",
 "last_name"=>"sdf",
 "email"=>"sdfg@sgf.com"}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,只有第一个order_item具有colour_id属性.无论选择的单选按钮属于哪种型号(这都有意义),都会发生这种情况.

如何渲染单选按钮,以便为每个子模型创建单独的组?

EmF*_*mFi 3

当您调用 fields_for 时,您必须为每个订单项指定一个唯一索引。如果您以这种方式调用 fields_for,则需要跟踪传递给 fields_for 的数组的索引。Rails 可以通过使用嵌套表单来为您完成此操作。

解决方案是使用嵌套表单。

<%form_for :order do |f|%>
  Form stuff for this particular order.
  If @order.order_items is empty you may need to build one before the next line.
  <%f.fields_for :order_items do |oi_f| %>
    Form stuff for this particular order_item (prefixed with oi_f.)
    <%Colour.all.each do |colour| %>
      <%=oi_f.radio_tag(:colour_id, colour.id)%>
    <%end%>
  <%end%>
<%end%>
Run Code Online (Sandbox Code Playgroud)

看起来您正在发布到orders_controller,因此这应该是替代品。