what wrong in this nested form?

I have:

class Company < ActiveRecord::Base   has_many :categorizations   has_many :categories, :through => :categorizations   has_many :managements   has_many :managers, :through => :managements   has_many :tenders   has_many :documents, :dependent => :destroy

  accepts_nested_attributes_for :managers   accepts_nested_attributes_for :documents   accepts_nested_attributes_for :categorizations

then the form is:

= semantic_form_for @company do |f|   = f.input :name = f.semantic_fields_for :manager do |manager|   = manager.inputs :name, :fiscal_code, :city, :zip_code, :address, :street_number, :tel, :email

when I submit the form raise the error:

unknown attribute: manager

{"utf8"=>"✓", "authenticity_token"=>"V5GsRKLK8cRrGuUh2Jv4DB9wSYWG8ASCxHkd0Ur3o8s=", "company"=>{"manager"=>{"name"=>"", "fiscal_code"=>"", "city"=>"", "zip_code"=>"", "address"=>"", "street_number"=>"", "tel"=>"", "email"=>""}}, "commit"=>"Create Company"}

I think there is nothing wrong but perhaps I miss something.

I have:

class Company < ActiveRecord::Base

has_many :categorizations

has_many :categories, :through => :categorizations

has_many :managements

has_many :managers, :through => :managements

has_many :tenders

has_many :documents, :dependent => :destroy

accepts_nested_attributes_for :managers

accepts_nested_attributes_for :documents

accepts_nested_attributes_for :categorizations

then the form is:

= semantic_form_for @company do |f|

= f.input :name

= f.semantic_fields_for :manager do |manager|

= manager.inputs :name, :fiscal_code, :city, :zip_code, :address,

:street_number, :tel, :email

when I submit the form raise the error:

unknown attribute: manager

{“utf8”=>“✓”,

“authenticity_token”=>“V5GsRKLK8cRrGuUh2Jv4DB9wSYWG8ASCxHkd0Ur3o8s=”,

“company”=>{“manager”=>{“name”=>“”,

“fiscal_code”=>“”,

“city”=>“”,

“zip_code”=>“”,

“address”=>“”,

“street_number”=>“”,

“tel”=>“”,

“email”=>“”}},

“commit”=>“Create Company”}

I think there is nothing wrong but perhaps I miss something.

If I am not mistaken, accepts_nested_attributes_for :managers adds a setter method of the style company.managers_attributes=

I think your hash that is coming in from the Submit tries to do company.manager= {“name”

=>“”,

“fiscal_code”=>“”,

“city”=>“”,

“zip_code”=>“”,

“address”=>“”,

“street_number”=>“”,

“tel”=>“”,

“email”=>“”}

and Rails complains that ‘manager’ is not an attribute of company (really saying that the Company#manager= methods is not defined).

To validate this hypothesis, try something like, e.g. in rails console

Company.new.methods.grep(/manager/)

and check which exact methods are available for ‘manager*’ on the Company class. I would expect you see there:

[… :managers_attributes=, …]

I think (not sure) a second problem is that the has_many requires an array there …

So, you should change your form to create parameters like this:

“company”=>{“managers_attributes”=>[ # key changed; changed into array

{“name”=>“P”,

“fiscal_code”=>“1”, “city”=>“2560”, …}, {“name”=>“S”,

“fiscal_code”=>“2”,

“city”=>“2500”,

…}]}, …

Also see:

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

Which shows as example:

class Member < ActiveRecord::Base
  has_many :posts
  accepts_nested_attributes_for :posts
end

You can now set or update attributes on an associated post model through the attribute hash.

For each hash that does not have an id key a new record will be instantiated, unless the hash also contains a _destroy key that evaluates to true.

params = { :member => {
:name => 'joe', :posts_attributes => [
{ :title => 'Kari, the awesome Ruby documentation browser!' },
{ :title => 'The egalitarian assumption of the modern citizen' },
{ :title => '', :_destroy => '1' } # this will be ignored
  ]
}}

Not entirely sure, but I think this is your problem.

Peter

Here is the grep result:

[:before_remove_for_managers=, :after_remove_for_managers, :after_add_for_managers?, :autosave_associated_records_for_managers, :manager_ids=, :after_remove_for_managers?, :validate_associated_records_for_managers, :before_remove_for_managers?, :before_add_for_managers, :after_add_for_managers=, :before_add_for_managers?, :managers, :before_add_for_managers=, :after_remove_for_managers=, :after_add_for_managers, :managers=, :before_remove_for_managers, :manager_ids]

there is a method managers so I changed

manager.semantic_fields_for :manager to manager.semantic_fields_for :managers

and in the controller

@company.managers.build

now it seems to work. Thank you.

But now I have a question:

if I do semantic_fields:_for :manager without doing @company.managers.build I see the manager form. Why I see the manager form? Do fields_for :manager call the manager controller?

Look in development/log to see what actions are being called and what is being rendered. Also have a look at the Rails Guide on debuging. That will show you how to use ruby-debug to break into your code and see what is happening.

Colin

Actually, to get ruby-debug working on Rails 3.1.x with ruby 1.9.3-p0 I had to play quite some tricks …

http://rails.vandenabeele.com/blog/2011/12/21/installing-ruby-debug19-with-ruby-1-dot-9-3-on-rvm/

Is that normal, or did I overlook something trivial ?

Peter

I have:

class Company < ActiveRecord::Base

has_many :categorizations

has_many :categories, :through => :categorizations

has_many :managements

has_many :managers, :through => :managements

has_many :tenders

has_many :documents, :dependent => :destroy

accepts_nested_attributes_for :managers

accepts_nested_attributes_for :documents

accepts_nested_attributes_for :categorizations

then the form is:

= semantic_form_for @company do |f|

= f.input :name

= f.semantic_fields_for :manager do |manager|

= manager.inputs :name, :fiscal_code, :city, :zip_code, :address,

:street_number, :tel, :email

when I submit the form raise the error:

unknown attribute: manager

{“utf8”=>“✓”,

“authenticity_token”=>“V5GsRKLK8cRrGuUh2Jv4DB9wSYWG8ASCxHkd0Ur3o8s=”,

“company”=>{“manager”=>{“name”=>“”,

“fiscal_code”=>“”,

“city”=>“”,

“zip_code”=>“”,

“address”=>“”,

“street_number”=>“”,

“tel”=>“”,

“email”=>“”}},

“commit”=>“Create Company”}

I think there is nothing wrong but perhaps I miss something.

If I am not mistaken, accepts_nested_attributes_for :managers

adds a setter method of the style company.managers_attributes=

I think your hash that is coming in from the Submit tries to do

company.manager= {“name”

=>“”,

“fiscal_code”=>“”,

“city”=>“”,

“zip_code”=>“”,

“address”=>“”,

“street_number”=>“”,

“tel”=>“”,

“email”=>“”}

and Rails complains that ‘manager’ is not an attribute of company

(really saying that the Company#manager= methods is not defined).

To validate this hypothesis, try something like, e.g. in rails console

Company.new.methods.grep(/manager/)

and check which exact methods are available for ‘manager*’ on the Company

class.

I would expect you see there:

[… :managers_attributes=, …]

Here is the grep result:

[:before_remove_for_managers=, :after_remove_for_managers,

:after_add_for_managers?, :autosave_associated_records_for_managers,

:manager_ids=, :after_remove_for_managers?,

:validate_associated_records_for_managers,

:before_remove_for_managers?, :before_add_for_managers,

:after_add_for_managers=, :before_add_for_managers?, :managers,

:before_add_for_managers=, :after_remove_for_managers=,

:after_add_for_managers, :managers=, :before_remove_for_managers,

:manager_ids]

Did you remove the line

accepts_nested_attributes_for :managers

to obtain this result above? Otherwise, I don’t understand why the method :managers_attributes= does not show in the list …

there is a method managers so I changed

manager.semantic_fields_for :manager

to

manager.semantic_fields_for :managers

and in the controller

@company.managers.build

Do you mean you are now building a new manager from the hash, like:

@company.managers.build(params[:company][:managers]) #untested, not exactly sure

This may indeed work. But then you are not using the

accepts_nested_attributes_for functionality… It may be better to stick with accepts_nested_attributes_for and adapt your form to generate the managers_attributes hash.

But maybe I misunderstood …

Peter

Did you remove the line

accepts_nested_attributes_for :managers

perhaps it's my mistake, sorry. Company.new.grep(/manager/)

[:before_remove_for_managers=, :after_remove_for_managers, :after_add_for_managers?, :autosave_associated_records_for_managers, :manager_ids=, :after_remove_for_managers?, :validate_associated_records_for_managers, :before_remove_for_managers?, :before_add_for_managers, :after_add_for_managers=, :before_add_for_managers?, :managers_attributes=, :managers, :before_add_for_managers=, :after_remove_for_managers=, :after_add_for_managers, :managers=, :before_remove_for_managers, :manager_ids