Rails 3 Nested Models in one form using Formtastic and Cocoon gems

This post shows how to handle nested models in one form with the parent model.

Let our models be projects and tasks:

– project with title and description;

– task has title;

– each project may have many tasks.

 

We want to create a form where we can edit project attributes and edit (add/remove/edit) multiple tasks for this project.

We will use Formtastic gem for building forms and Cocoon gem for making nested forms. Using these gems it is really easy to handle nested models.

Find the solution how to do it without using Formtastic and Cocoon gems – here.

 

Gems

Gemfile:

gem 'formtastic'
gem 'cocoon'

 

Models




  Run this mysql script to create tables in a database:  


Javascript for Cocoon




 

Views

Edit your form to edit parent object. Add this code to include nested objects (tasks):

= f.inputs :name => "Tasks" do
    = f.semantic_fields_for :tasks do |task|
      = render "task_fields", :f => task
    .links
      = link_to_add_association 'Add task', f, :tasks

 

So your form will look like this:  

 

Partial view for task:




 

That’s it!

Your form should work so you can add new task to the project, edit existing tasks of the project or remove tasks in this form.

 

Issues

Error “Can’t mass-assign protected attributes”

You may get an error “Can’t mass-assign protected attributes: <nested_model_name>_attributes”.

In this case check that you have the following code in your parent model:

class Project < ActiveRecord::Base
attr_accessible .., :tasks_attributes
has_many :tasks, :dependent => :destroy
accepts_nested_attributes_for :tasks, :reject_if => lambda { |a| a[:title].blank? }, :allow_destroy => true
..
end

 

 

References:

* Tutorial – http://railscasts.com/episodes/196-nested-model-form-part-1

* https://github.com/ryanb/nested_form – gem for conveniently manage multiple nested models in a single form. It does so in an unobtrusive way through jQuery or Prototype.

* https://github.com/nathanvda/cocoon – Cocoon makes it easier to handle nested forms.