Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Nested Object Form *_attributes

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!

like image 340
dr. Avatar asked Apr 12 '09 22:04

dr.


3 Answers

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

like image 109
nowk Avatar answered Nov 15 '22 09:11

nowk


Try to use an actual object for form_for:

form_for :person => form_for @person
like image 4
alloy Avatar answered Nov 15 '22 07:11

alloy


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.

like image 1
tsdbrown Avatar answered Nov 15 '22 07:11

tsdbrown