Blog

Nested objects with Formtastic

Jonathon Horsman Mar 16 3 comments

After several hours beating my head against a desk trying to get my nested Formtastic form working, I figured out the reason.

Assuming you have a simple Rails one-to-many relationship:

class Candidate < ActiveRecord::Base
  has_many :jobs
end

class Job < ActiveRecord::Base
  belongs_to :candidate
end

and you have a form which can update our candidate and up to 3 jobs at the same time, so we prepare that in our controller:

class CandidatesController < ApplicationController
  def new
    @candidate = Candidate.new
    3.times do
      @candidate.jobs.build
    end
  end
end

so the form allows creation of the candidate and 3 jobs too:

<% semantic_form_for @candidate do |f| %>
  <%= f.inputs %>
  <%= f.inputs :for => :jobs do |j| %>
    <%= j.input :name %>
  <% end %>
<% end %>

but for some reason this just didn’t work.

The jobs input displayed only once and j.object was nil.

After some searching and head scratching I finally figured this out, which isn’t mentioned on the Formtastic site. You need to use accepts_nested_attributes_for.

So the model will look like this:

class Candidate < ActiveRecord::Base
  has_many :jobs
  accepts_nested_attributes_for :jobs
end

class Job < ActiveRecord::Base
  belongs_to :candidate
end

And then it works!

Comments //

cncard

cncard Apr 02

Thanks for the tip.

The formtastic docs mention:
"Nested forms (Rails 2.3) are also supported (don’t forget your models need to be setup correctly with accepts_nested_attributes_for – search the Rails docs)."

I think the accepts_nested_attributes_for :jobs
goes in the Candidate class

Jonathon Horsman

Jonathon Horsman Apr 05

Yep, the docs do mention that now... after I wrote this post I asked Justin to amend his docs which he kindly obliged :-)

Matt Huggins

Matt Huggins Dec 07

Thanks for sharing this, I couldn't seem to find info on how to do this anywhere! One question I have though, do you know how to add an index to the label for each nested object? For example, how would I dynamically make the labels display "Object 1", "Object 2", "Object 3", etc. while doing this?

Post a comment

  1. optional

Recent Tweets

Blog: The monumental Myspace cock-up: http://bit.ly/emgRKV
Tweeted on Friday at 09:43

Awww railsapi, delete some logs: http://bit.ly/htBNDH
Tweeted on Wednesday at 16:15