Rails fields_for: объяснение опции child_index - PullRequest
25 голосов
/ 21 мая 2010

Я пытался создать сложную форму со многими вложенными моделями и сделать ее динамичной. Теперь я обнаружил, что создание вложенной модели не сложно с accepts_nested_attributes_for, но сделать ее вложенной и динамичной было бы, казалось бы, невозможно, если было несколько вложенных моделей.

Я сталкивался с http://github.com/ryanb/complex-form-examples/blob/master/app/helpers/application_helper.rb, что делает это очень элегантно. Может ли кто-нибудь пролить свет на строки 13 и 16?

13 form_builder.object.class.reflect_on_association(method).klass.new

и

16 form_builder.fields_for(method, options[:object], :child_index => "new_#{method}") do |f|

Из интуиции в строке 13 создается новый объект, но почему он должен выполнять так много вызовов методов? Я не смог найти никакой документации по параметру: child_index в строке 16. При создании формы очень большое число используется в качестве индекса для новых моделей, тогда как существующие модели индексируются по их идентификатору. Как это работает?

1 Ответ

41 голосов
/ 21 мая 2010
options[:object] ||= form_builder.object.class.reflect_on_association(method).klass.new

Если объект не передается в качестве параметра, создается новый объект соответствующего класса.

form_builder.object получает основной объект из формы (project)

form_builder.object.class получает свой класс (Project)

method - название ассоциации для Проекта (:tasks)

refle_on_association (метод) дает AssociationReflection объект.

refle_on_association (метод). класс возвращает класс ассоциации. (Task)

И, наконец, klass.new создает новый экземпляр (Task.new => новая задача)

Это делается так, потому что имя ассоциации не всегда является просто именем класса во множественном числе, как в этом случае (Task -: tasks), но необходимо получить объект класса для создания его нового экземпляра.

form_builder.fields_for(method, options[:object], :child_index => "new_#{method}") do |f|
Опция

:child_index позволяет указать индекс конкретного объекта:

project[tasks_attributes][:child_index][field_name]

Он устанавливается в "" новый _ # {метод} "Rails, но затем заменяется на javascript (application.js):

function insert_fields(link, method, content) {
  var new_id = new Date().getTime();
  var regexp = new RegExp("new_" + method, "g")
  $(link).up().insert({
    before: content.replace(regexp, new_id)
  });
}

Индекс имеет большое значение, чтобы не конфликтовать с существующими элементами. Кстати, они не индексируются по id, просто от 0 до count-1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...