fields_for and Conflicting types for parameter containers. Expected an instance of Hash but found an instance of Array.

I'm trying to use 'fields_for' in a form. I want the same form to support both the creation of new obejcts as well as the editing of old ones. So - in my controller, sometimes I will pass to the form an object that already exists in my database and has an id and other times I will pass it a newly created instance of an object that does not yet exist in the database and does not have an id.

I want the params hash to have the id of the object if its available, so - i'm using fields_for 'vehicle_record', as opposed to fields for 'vehicle_record'.

Also, when I am using the form to render an existing object, i'd like it to automatically display the values of the existing parameters wherever I use f.text_field. And - i'd like it to package up those params that exist into a nice params hash.

When my controller passes the view an existing object, I submit the form and everything's dandy. When my controller passes the view a new object that does not have an id, then I get the error message regarding conflicting container types.

Why? Can I use the same form to handle both new and edited objects and at the same time to work as expected with f.text_field? Am I going about it the wrong way? I spent quite a bit of time reading the tutorials on the web but still don't understand what's going on here.

Any guidance appreciated! Yoram

When my controller passes the view an existing object, I submit the form and everything's dandy. When my controller passes the view a new object that does not have an id, then I get the error message regarding conflicting container types.

Why? Can I use the same form to handle both new and edited objects and

Well it's a little tricky to say without seeing the html but that error message usually means that in the same form you have something like foo=bar and foo[bar]=baz

it may be that passing an :index option to fields for when dealing with a new record is the way out

Fred

Fred, thanks. Your explanation led me right to the problem: I had a variable that I wanted to associate with the model object, but just for the life of this form. In a sense it's a 'virtual' attribute because I have no column in the database for it. So - I couldn't use f.text_field for it. Instead, I tried to force rails to package it up in a nice params hash by manually writing out the html for this attribute in the following manner: "blah blah id="vehicle_record_miles_driven" name="vehicle_record[miles_driven]". When I passed the view an object with an existing id, this worked fine. Otherwise - it caused the conflict. So - now that I know the root of the conflict, next question: what is the conventional way to handle such 'virtual' attributes? Would it be to simply create a read and write accessor for it?

Second question related to forms: When I use fields_for 'vehicle_record' (and I remove the offending html), rails produces a params hash that: In the case of a new object with no id: has a key: 'vehicle_record' with a corresponding value that is an array of hashes of the attributes. In the case of an existing object that has an id: has a key: 'vehicle_record' with a corresponding value that is itself a hash with a key equal to the id of the object and a value that is the attributes of the object.

So - what's the conventional manner for handling this in the controller? I could just query to see if params ['vehicle_record'].class == Array vs. hash and then decide based on that whether to parse it as a new object or an existing one, but that seems a little inelegant.

On the other hand, I could use 'form_for' which generates the same params hash format for both cases (existing and new object) but does not include an id. In this case, I would have the controller pass the view an instance variable: @record_id = 'foo' (in the case of an existing object or @record_id = nil (in the case of a new one. Then i'd pass it back as a hidden field and i'd use a nil value to indicate that it's a new object. This seems similar to your suggestion to use the 'index' option.

So, basically - i'm asking what the conventional manner for doing this is... In the abstract, the problem is creating a controller and form that can handle either a new object or an existing one while fully leveraging all the goodness that rails provides. After a bunch of reading on this, i've yet to find a 'convention' for this.

Thanks always for your generous support!

Yoram

On the other hand, I could use 'form_for' which generates the same params hash format for both cases (existing and new object) but does not include an id. In this case, I would have the controller pass the view an instance variable: @record_id = 'foo' (in the case of an existing object or @record_id = nil (in the case of a new one. Then i'd pass it back as a hidden field and i'd use a nil value to indicate that it's a new object. This seems similar to your suggestion to use the 'index' option.

So, basically - i'm asking what the conventional manner for doing this is... In the abstract, the problem is creating a controller and form that can handle either a new object or an existing one while fully leveraging all the goodness that rails provides. After a bunch of reading on this, i've yet to find a 'convention' for this.

Have you looked at the new complex forms stuff ?

Fred

Yes but somehow I thought that what i'm trying to do here is pretty simple and that it would not require complex form stuff. Maybe I should study the complex form stuff more closely. Thanks for the pointer.

Fred, thanks. Your explanation led me right to the problem: I had a variable that I wanted to associate with the model object, but just for the life of this form. In a sense it's a 'virtual' attribute because I have no column in the database for it. So - I couldn't use f.text_field for it. Instead, I tried to force rails to package it up in a nice params hash by manually writing out the html for this attribute in the following manner: "blah blah id="vehicle_record_miles_driven" name="vehicle_record[miles_driven]". When I passed the view an object with an existing id, this worked fine. Otherwise - it caused the conflict. So - now that I know the root of the conflict, next question: what is the conventional way to handle such 'virtual' attributes? Would it be to simply create a read and write accessor for it?

Yes, with accessors you should just be able to use f.text_field etc...

Second question related to forms: When I use fields_for 'vehicle_record' (and I remove the offending html), rails produces a params hash that: In the case of a new object with no id: has a key: 'vehicle_record' with a corresponding value that is an array of hashes of the attributes. In the case of an existing object that has an id: has a key: 'vehicle_record' with a corresponding value that is itself a hash with a key equal to the id of the object and a value that is the attributes of the object.

by passing an index option you can force what fields_for uses (by
default it's the record's id and blank if the record is unsaved. THere
are various ways you can generated what   identifiers you autogenerate for new records, that's one of the
things I think the complex forms stuff covers.

Fred