Error when using form helper and child objects


#1

Hi,

This is one problem that has gotten me stumped for quite a while. I have
an Item that has_many :DeliveryMethod, and what I seek to achieve is to
create a form that’d let me create an Item, as well as its
DeliveryMethods in 1 single form.

And so I tried something like:

<%= text_field_tag ‘Item[DeliveryMethod][price]’, @Item.DeliveryMethod
? @Item.DeliveryMethod.price : nil %>

But I’ve received an application error `@auction[DeliveryMethod][price]’
is not allowed as an instance variable name

Can someone please give me some pointers to what I might have
overlooked? I got that format from an earlier posting in this mailing
list, but it seems like I must have missed something.

Thank you.


#2

On 2/4/06, Woei S. removed_email_address@domain.invalid wrote:

? @Item.DeliveryMethod.price : nil %>

But I’ve received an application error `@auction[DeliveryMethod][price]’
is not allowed as an instance variable name

Can someone please give me some pointers to what I might have
overlooked? I got that format from an earlier posting in this mailing
list, but it seems like I must have missed something.

A couple of things are going on here.

  1. The form helpers are expecting to receive the names of instance
    variables and methods (as strings) as their parameters.
    text_field_tag ‘Item[DeliveryMethod][price]’ is going to look for an
    instance variable called @Item[DeliveryMethod][price], which isn’t a
    valid name.

  2. Each call to text_field or text_field_tag will only emit one
    tag. You need to call it once for every field you need in the
    output.

  3. Item has_many DeliveryMethods, but you’re treating it as a has_one
    in the above code.

This is roughly how I’d go about what you’ve described:

models

class Item < ActiveRecord::Base
has_many :delivery_methods
end

class DeliveryMethod < ActiveRecord::Base
belongs_to :item
end

controller

def show
@item = Item.find params[:id]
end

show.rhtml

Other stuff here… and then…

<%= text_field ‘item’, ‘some_method_that_item_has’ %>
<%= text_field ‘item’, ‘something_else_singular’ %>

<% if @item.delivery_methods -%>
<%= render :partial => ‘delivery_method’, :collection =>
@item.delivery_methods %>
<% end -%>

_delivery_method.rhtml ### (partial form)

<% @delivery_method = delivery_method -%> # The helpers require
instance methods, but the partial creates a local variable.
<% i = delivery_method_counter -%> # I hate typing
delivery_method_counter a dozen times.
<%= text_field ‘delivery_method’, ‘price’, :index => i %>

You can do this without partials, via @item.delivery_methods.each, or
a ‘for’ loop, but I prefer the extra separation offered by the partial
forms.
Notice the use of the :index => option, which lets Rails know you’re
making an array of fields.

In the controller, params[:delivery_method] will contain a hash of all
the delivery methods.
params[:delivery_method].each do |index, value|
#index starts at ‘0’
#value contains whatever the user entered on the form.
end