Как получить правильные идентификаторы детей с помощью fields_for "parent []", parent do | f | используя f.fields_for: children, child? - PullRequest
2 голосов
/ 25 июня 2011

Я редактирую несколько экземпляров родительской модели в представлении индекса в одной форме, как в Railscasts # 198.У каждого родителя есть has_many: children и acceptpts_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="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 = "parent_1 ___ children_chore"

, который получает правильный parent_index, но не предоставляет слот массива для дочернего индекса.

"[] children []" также не прав: id = "parent_1__children_3_chore"

, поскольку я ожидал атрибуты_0_chore вместо 3_chore.

Нужно ли мне напрямую изменять атрибут объекта FormBuilder или подкласс FormBuilder, чтобы это работало, или есть синтаксис, который соответствует этой ситуации?

Спасибо за любые мысли.

1 Ответ

6 голосов
/ 01 июля 2011

Я решил эту проблему, прочитав исходный код FormBuilder.fields_for

Один из возможных ответов: Да, измените атрибут f.object_name объекта FormBuilder.

Конкретно в этой ситуации

f.fields_for :children  

будет вызывать

f.fields_for_with_nested_attributes

, который устанавливает переменную имени на основе f.object_name.Идентификатор сгенерированного элемента выглядит так, как будто он основан на имени, поэтому оба результата совпадают в полученном html.

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

Так что один из способов сказать f.fields_for, что я хотел сделать, - установить f.имя_объекта для включения родительского идентификатора на время блока f.fields_for

<% 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 может использовать стандартные помощники рельсов без изменений.

...