Fields_for and Conflicting types for parameter containers. Expected an instance of Hash but found a


#1

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


#2

On Feb 18, 5:38 am, “removed_email_address@domain.invalid” removed_email_address@domain.invalid wrote:

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


#3

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 Feb 18, 12:17 am, Frederick C. removed_email_address@domain.invalid


#4

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.

On Feb 18, 5:43 am, Frederick C. removed_email_address@domain.invalid


#5

On 18 Feb 2009, at 13:29, removed_email_address@domain.invalid wrote:

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…

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


#6

On 18 Feb 2009, at 13:29, removed_email_address@domain.invalid wrote:

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