The Problem

If you work with web applications on a a regular basis, at some point you're going to have to deal with gathering user input for storage in a database or for passing on via email. As you start to model more complex "problem domains, you will find that the forms that you require for gathering related input become much more complex.

For instance, let's take a simplistic example. A "Company" has many "Addresses" as shown by the diagram below.

If you want to create a form that prompts the user for both company and address information, you will need to "nest" the address fields within the company form. So, how do we do it? Well, until recently it was a bit of a hassle, however, "Nested Object Forms" is a new feature in Rails 2.3, which aims to simplify this process. Yah!

So, the Company and Address objects, described above, can be described using the following models:-

http://gist.github.com/200218.js">

How accepts_nested_attributes_for Can Help

To allow a company form to have nested address fields pre Rails 2.3 you would have to create several attributes that enabled the nested fields to be saved/retrieved from the database. However, in Rails 2.3 we can use the "accepts_nested_attributes_for" method to do a lot of the donkey work for us. To do this, simply change the "Company" model to look like the following:-

http://gist.github.com/200219.js">

Very simple! Essentially, the accepts_nested_attributes_for method integrates the required functionality to allow you to save and retrieve the associated address record(s).

The view will use fields_for, as per usual, to display these related fields:-

http://gist.github.com/200221.js">

One thing to notice in the above example is the setup_company method call. We have yet to set this method up - let's do it now! In your application helper file add the following:-

http://gist.github.com/200225.js">

The method build the required child object in memory, so that the required blank fields appear on the form when creating and editing a company record.

Thats it!