6

I'm using Rails 2.3.2, and trying to get a nested object form to work properly. I've narrowed my problem to the issue that Rails is not setting my nested form elements with the *_attributes required to initiate the accepts_nested_attributes_for processing.

My model code is:

class Person < Party
  has_one :name, :class_name => "PersonName"
  accepts_nested_attributes_for :name, :allow_destroy => true
end

class PersonName < ActiveRecord::Base
  belongs_to :person
end

My view code looks like this (I'm using HAML):

%h3 New customer
= error_messages_for :person, :person_name, :name, :country

- form_for :person, :url => collection_url, :html => {:class => 'MainForm'} do |person_form|

  - @person.build_name unless @person.name
  - person_form.fields_for :name do |name_form|
    = name_form.label :given_name, "First Name:"
    = name_form.text_field :given_name

    = name_form.label :family_name, "Last Name:"
    = name_form.text_field :family_name

  = hidden_field_tag :inviter_id, params[:inviter_id]
  = hidden_field_tag :inviter_code, params[:inviter_code]
  %p= submit_tag "Create"

= link_to 'Back', collection_url

Instead of params being:

{"person"=>{"name_attributes"=>{"given_name"=>"Fred", "family_name"=>"Flintstone"}}, ...} 

I get:

{"person"=>{"name"=>{"given_name"=>"Fred", "family_name"=>"Flintstone"}}, ...} 

As a result, I get a TypeMismatch exception. I've followed the documentation from Ryan Daigle. I've also followed the advice from this blog and the complex-forms-example.

Using Firebug, I went through my form and adjusted the name attribute of the input tags from name to name_attributes. This produced the params with name_attributes, and the create worked fine.

I'm stuck as I cannot figure out why my form is not producing the *_attributes form of the name.

Another thing I tried is I got the complex_form_example working in my environment. I've gone through every inch of the controller, models and views and compared it to my code. I cannot find what is different. I know this is something small, and would appreciate any help!

Thanks!

5
  • What does your view code look like? Commented Apr 12, 2009 at 22:33
  • I added a representation of my view code. Commented Apr 13, 2009 at 4:24
  • Note: It doesn't work either if you haven't defined the 'accepts_nested_attributes' option! But that's okay in your case :). Commented Jun 8, 2009 at 8:07
  • But I have defined the 'accepts_nested_attributes' option Commented Jun 23, 2009 at 17:01
  • I was having the same problem as the OP, and the response by tsdbrown worked for me as well. I don't totally understand why... I have other rails apps that work as "they should". tsdbrown's response: stackoverflow.com/questions/742536/… Commented Nov 6, 2009 at 23:17

6 Answers 6

4

Post backs do not get routed to the right place

def new
  @person = Person.new
end

<% form_for @person do |f| %>
    <% f.fields_for :name_attributes do |p| %>
        ...
    <% end %>
<% end %>

Post backs get routed to the right place

def new
  @person = Person.new
  @person.name = PersonName.new # << this allows fields_for :relation vs :relation_attributes
end

<% form_for @person do |f| %>
    <% f.fields_for :name do |p| %>
        ...
    <% end %>
<% end %>

No need to @person.name again in #create

Sign up to request clarification or add additional context in comments.

1 Comment

You could also write: @person.build_name instead of @person.name = PersonName.new see: api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/…
4

Try to use an actual object for form_for:

form_for :person => form_for @person

1 Comment

This solved it in my case. Not sure why shouldn't work with the symbolized notation...
1

I have just been struggling for about an hour with exactly the same problem!

Follow nowk's pattern for the new method in the controller, then put this in your view

<% form.fields_for :name, @person.name do |name_form| %>


<% end %>

Good luck if you try it, that's what worked for me.

1 Comment

Yep, that's the way. Take a good gander at the docs: fields for
0

Not sure why this isn't working for, but as a workaround, you could just use params[:name] in your controller#create method to update the person record.

person = Person.new(params[:person])
person.name << PersonName.new(params[:name])

2 Comments

Thanks for your work-around suggestion. I can work around the issue using active_presenter. I'm trying to implement this using 2.3 nested object forms the right way so I can learn how to use it properly.
Cool. If you found a solution with using nested object forms, maybe you could post it, for the sake of others?
0

Unfortunately, I still have not been able to figure out why this form wouldn't work with nested object forms. I stripped it down to the simplest data, started over using the complex-form-example as a start. I ended using the active_presenter to gather x-object data from the form. I'll revisit nested object forms sometime in the form. Thanks for your help.

Comments

0

Thought I would share my solution as it's slightly different - in my case I want the nested attributes to be dynamic.

In new action:

  case params[:type]
  when "clubber"
    @account = resource.send "build_#{params[:type]}"
  when "promoter"
    @account = resource.send "build_#{params[:type]}"
  when "company"
    @account = resource.send "build_#{params[:type]}"
  when "venue_owner"
    flash[:notice] = 'We ask that venue owners register via the web. Thanks.'
    redirect_to root_path and return
  end

In my view:

= f.fields_for @account.class.name.downcase+'_attributes' do |form|

Pretty ghetto, but it works.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.