Creates a scope around a specific model object like form_for, but
doesn’t create the form tags themselves. This makes fields_for
suitable for specifying additional model objects in the same form. Example:

When using nested attributes mass assignment sometimes you will want to add
new records with javascript. You can do it with pure javascript, but if HTML is long your javascript will be long and messy
and it will not be DRY as probably you already have a partial for it.

So to add a partial dynamically you can do something like that (notice
string “index_to_replace_with_js”):

If you implement your own formbuilder, the options passed are available as
@options inside your formbuilder. If you want those configuration
options passed to all builders in the fields_for
sections, use the following code in your form builder:

Using add_object_link

I had the @colleagues collection prepared that I wanted to be rendered
within fields_for
block. However it was searchlogic object with filtering/sorting applied,
and the sort order was not preserved in resultant view.

But fields_for is
defined both on FormBuilder and FormHelper
and is still useful even when accepts_nested_attributes_for is not being
used. Consider a “to do list” application where we wish to edit and
update a list of tasks (Task model). I like to use a
TaskCollectionController to manage the actions on the collection, it feels
more RESTful than overloading a TaskController:

class TaskCollectionController<ApplicationController# task_collection_edit GET /task_collection/edit def edit@tasks=Task.allend# task_collection_update PUT /task_collection/updatedef update# it would be better to use a TaskCollection form object here# to make this controller skinny,# for the sake of brevity I skipped the form objectparams[:tasks].values.eachdo|attrs|ifattrs[:_destroy]=='1'Task.find(attrs[:id]).destroyelsifattrs[:id].blank?Task.create(attrs.slice!(:id,:_destroy))elseTask.find(attrs[:id]).update_attributes(attrs.slice!(:id,:_destroy))endendredirect_totask_collection_edit_pathendend

In the edit view, I use fields_for to
index added tasks, and it also will insert the id as a hidden field for
existing tasks:

:hidden_field_id => true triggers the insertion of the id field, and a
placeholder index “NEW_RECORD” is replaced by javascript when a task is
added, as others have described here. When there’s no association, the
index key is :index, vs. :child_index in the case of an association.

module TaskCollectionHelperdef remove_item(form_builder)ifform_builder.object.new_record?# If the task is a new record, remove the div from the domlink_to_function('Remove',"$(this).closest('tr').remove()")else# However if it's a "real" record it has to be deleted from the database,# hide the form and mark for destructionform_builder.hidden_field(:_destroy)+link_to_function('Remove',"$(this).closest('tr').hide(); $(this).siblings().attr('value',1)")endendend