Направляющие fields_for: объяснение опции child_index

Я пытался создать сложную форму со многими вложенными моделями и сделать ее динамичной. Теперь я нашел, что создание вложенной модели не является трудным с 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. Когда форма создается, очень большое количество используется в качестве индекса для новых моделей, тогда как существующие модели индексируются их идентификатором. Как это работает?

25
задан Timothy 21 May 2010 в 02:20
поделиться

1 ответ

options[:object] ||= form_builder.object.class.reflect_on_association(method).klass.new

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

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

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

method - имя ассоциации для Project (:tasks)

reflect_on_association(method) дает объект AssociationReflection.

reflect_on_association(method). klass возвращает класс ассоциации. (Task)

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

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

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

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

project[tasks_attributes][:child_index][field_name]

Он устанавливается в `"new_#{method}" 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

41
ответ дан 28 November 2019 в 21:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: