2010-05-21 8 views
21

He intentado crear un formulario complejo con muchos modelos anidados y hacerlo dinámico. Ahora descubrí que hacer un modelo anidado no es difícil con accept_nested_attributes_for, pero hacerlo anidado y dinámico era aparentemente imposible si había varios modelos anidados.Rails fields_for: child_index option explanation

Me encontré con http://github.com/ryanb/complex-form-examples/blob/master/app/helpers/application_helper.rb que lo hace muy elegantemente. ¿Alguien podría arrojar algo de luz sobre las líneas 13 y 16?

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

y

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

De la intuición, la línea 13 crea la instancia de un objeto nuevo, pero ¿por qué tiene que hacer tantas llamadas de método? No pude encontrar ninguna documentación para la opción: child_index en la línea 16. Cuando se crea el formulario, se usa un número muy grande como índice para los nuevos modelos, mientras que los modelos existentes se indexan por su id. ¿Como funciona esto?

Respuesta

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

Si el objeto no se pasa como parámetro, crea un nuevo objeto de la clase correspondiente.

form_builder.object obtiene el objeto principal de la forma (project)

form_builder.object.class obtiene su clase (Project)

method es el nombre de la asociación para el Proyecto (:tasks)

reflect_on_association(method) da AssociationReflection objeto.

reflect_on_association (método). klass devuelve la clase de la asociación. (Task)

Y, por último, klass.new crea una nueva instancia (Task.new => nueva tarea)

Se hace de esta manera debido a que el nombre de la asociación no siempre es simplemente un nombre de clase pluralizado, como en este caso (Tarea -: tareas), pero es necesario obtener el objeto de la clase para crear una nueva instancia de la misma.

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

:child_index le permite especificar el índice del objeto particular:

project[tasks_attributes][:child_index][field_name] 

se establece en ` "nueva _ # {método}" por los carriles, pero luego se sustituye por el javascript (aplicación. 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) 
    }); 
} 

El índice se establece en un número grande para no entrar en conflicto con los elementos existentes. Por cierto, no están indexados por id, solo de 0 a count-1

+0

¿Cómo sabe Rails qué eliminar en la base de datos si está indexado de 0 a count - 1? Me estoy perdiendo algo. – Timothy

+4

Inserta el campo oculto para cada registro, que contiene su id: ''. Es una buena idea ver la fuente HTML para comprender qué genera Rails. – Voyta

+0

excelente explicación. Gracias. – user938363

Cuestiones relacionadas