开发者

How to get correct children ids using fields_for "parents[]", parent do |f| using f.fields_for :children, child?

I'm editing multiple instances of a parent model in an index view in one form, as in Railscasts #198. Each parent has_many :children and accepts_nested_attributes_for :children, as in Railscasts #196 and #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 %>  

Given parent.id==1

f.text_field :job correctly generates

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

But cf.text_field :chore generates ids and names that don't have the parent index.

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

If I try passing the specific child object to f.fields_for like this:

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

I get the same. If I change the method from :children to "[]children" I get

id="parents_1___children_chore"

which gets the right parent_index but doesn't provide an array slot for the child index.

"[]children[]" isn't right either: id="parents_1__children_3_chore"

as I was expecting attributes_0_chore instead of 3_chore.

Do I need to directly modify an attribute of the FormBuilder object, or subclass FormBuilder to make this work, or is there a syntax that fits this situation?

Thanks for any thought开发者_C百科s.


I did solve this problem by reading the source code for FormBuilder.fields_for

One possible answer: Yes, modify the f.object_name attribute of the FormBuilder object.

Specifically in this situation

f.fields_for :children  

is going to call

f.fields_for_with_nested_attributes

which sets the name variable based on f.object_name. The id for the generated element looks like it is based on the name,so both match in the resulting html.

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

So one way to tell f.fields_for to do what I wanted is to set f.object_name to include the parent id for the duration of the f.fields_for block

<% 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[]" %>

Then everything within the f.fields_for block can use the standard rails helpers unmodified.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜