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