I have been trying to create a complex form with many nested models, and make it dynamic. Now I found that making a nested model isn\'t difficult with accepts_nested_attribu
options[:object] ||= form_builder.object.class.reflect_on_association(method).klass.new
If the object is not passed as a parameter, it creates a new object of the corresponding class.
form_builder.object
gets the main object from the form (project
)
form_builder.object.class
gets its class (Project
)
method
is the association name for the Project (:tasks
)
reflect_on_association(method) gives AssociationReflection object.
reflect_on_association(method).klass returns the class of the association. (Task
)
And, finally, klass.new creates a new instance (Task.new
=> new task)
It is done this way because the association name is not always just a pluralized class name like in this case (Task - :tasks), but it is necessary to get the class object to create new instance of it.
form_builder.fields_for(method, options[:object], :child_index => "new_#{method}") do |f|
:child_index
option allows you to specify the index of particular object:
project[tasks_attributes][:child_index][field_name]
It is set to `"new_#{method}" by Rails, but is then replaced by 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)
});
}
Index is set to a large number just not to conflict with existing items. They are not indexed by id by the way, just from 0 to count-1