2

我正在以一种形式在索引视图中编辑父模型的多个实例,如 Railscasts #198 中所示。每个父节点 has_many :children 和 accept_nested_attributes_for :children,如 Railscasts #196 和 #197

<%= form_tag %>
  <% for parent in @parents %>
    <%= fields_for "parents[]", parent do |f|
      <%= f.text_field :job %>
      <%= f.fields_for :children do |cf| %>
         <% cf.text_field :chore %>
      <% end %> 
    <% end %> 
  <% end %> 
<% end %>  

给定 parent.id==1
f.text_field :job 正确生成

<input id="parents_1_job" type="text" value="coding" size="30" name="parents[1][job]">  

但是 cf.text_field :chore 生成没有父索引的 ID 和名称。

id="parents_children_attributes_0_chore"  
name="parents[children_attributes][0][chore]"    

如果我尝试像这样将特定的子对象传递给 f.fields_for:

<% for child in parent.children %>
  <%= f.fields_for :children, child do |cf| %>
    <%= cf.text_field :chore %>
  <% end %>
<% end %>  

我也一样。如果我将方法从 :children 更改为 "[]children" 我得到

id="parents_1___children_chore"

它得到正确的 parent_index 但不为子索引提供数组槽。

“[]children[]”也不对:id="parents_1__children_3_chore"

因为我期待attributes_0_chore 而不是3_chore。

我是否需要直接修改 FormBuilder 对象的属性或 FormBuilder 的子类才能使其工作,或者是否有适合这种情况的语法?

感谢您的任何想法。

4

1 回答 1

6

我确实通过阅读FormBuilder.fields_for的源代码解决了这个问题

一个可能的答案:是的,修改 FormBuilder 对象的 f.object_name 属性。

具体在这种情况下

f.fields_for :children  

会打电话

f.fields_for_with_nested_attributes

它根据 f.object_name 设置名称变量。生成元素的 id 看起来是基于名称的,因此两者在生成的 html 中都匹配。

def fields_for_with_nested_attributes(association_name, args, block)
      name = "#{object_name}[#{association_name}_attributes]"
.....

因此,告诉 f.fields_for 做我想做的事情的一种方法是将 f.object_name 设置为在 f.fields_for 块的持续时间内包含父 ID

<% old_object_name = f.object_name %>
<% f.object_name="parents[#{f.object.id}]" %>
<% =f.fields_for :children do |cf| %>
  <%= cf.text_field :chore %>
<% end %>
<% f.object_name=old_object_name #should be "parents[]" %>

然后 f.fields_for 块中的所有内容都可以使用未修改的标准 rails 助手。

于 2011-06-30T22:01:02.537 回答