h2. Rails nested model forms
Creating a form for a model _and_ its associations can become quite tedious. Therefor Rails provides helpers to assist in dealing with the complexities of generating these forms _and_ the required CRUD operations to create, update, and destroy associations.
In this guide you will:
* do stuff
endprologue.
NOTE: This guide assumes the user knows how to use the "Rails form helpers":form_helpers.html in general. Also, it’s *not* an API reference. For a complete reference please visit "the Rails API documentation":http://api.rubyonrails.org/.
h3. Model setup
To be able to use the nested model functionality in your forms, the model will need to support some basic operations.
First of all, it needs to define a writer method for the attribute that corresponds to the association you are building a nested model form for. The +fields_for+ form helper will look for this method to decide whether or not a nested model form should be build.
If the associated object is an array a form builder will be yielded for each object, else only a single form builder will be yielded.
Consider a Person model with an associated Address. When asked to yield a nested FormBuilder for the +:address+ attribute, the +fields_for+ form helper will look for a method on the Person instance named +address_attributes=+.
h4. ActiveRecord::Base model
For an ActiveRecord::Base model and association this writer method is commonly defined with the +accepts_nested_attributes_for+ class method:
h5. has_one
class Person < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
end
h5. belongs_to
class Person < ActiveRecord::Base
belongs_to :firm
accepts_nested_attributes_for :firm
end
h5. has_many / has_and_belongs_to_many
class Person < ActiveRecord::Base
has_many :projects
accepts_nested_attributes_for :projects
end
h4. Custom model
As you might have inflected from this explanation, you _don’t_ necessarily need an ActiveRecord::Base model to use this functionality. The following examples are sufficient to enable the nested model form behaviour:
h5. Single associated object
class Person
def address
Address.new
end
def address_attributes=(attributes)
# ...
end
end
h5. Association collection
class Person
def projects
[Project.new, Project.new]
end
def projects_attributes=(attributes)
# ...
end
end
NOTE: See (TODO) in the advanced section for more information on how to deal with the CRUD operations in your custom model.
h3. Views
h4. Controller code
A nested model form will _only_ be build if the associated object(s) exist. This means that for a new model instance you would probably want to build the associated object(s) first.
Consider the following typical RESTful controller which will prepare a new Person instance and its +address+ and +projects+ associations before rendering the +new+ template:
class PeopleController < ActionController:Base
def new
@person = Person.new
@person.built_address
2.times { @person.projects.build }
end
def create
@person = Person.new(params[:person])
if @person.save
# ...
end
end
end
NOTE: Obviously the instantiation of the associated object(s) can become tedious and not DRY, so you might want to move that into the model itself. ActiveRecord::Base provides an +after_initialize+ callback which is a good way to refactor this.
h4. Form code
Now that you have a model instance, with the appropriate methods and associated object(s), you can start building the nested model form.
h5. Standard form
Start out with a regular RESTful form: