Form question


#1

Suppose I have the following models/migrations:

class Car < ActiveRecord::Base
belongs_to :manufacturer
validates_presence_of :manufacturer
validates_association :manufacturer
end

class CreateCars < ActiveRecord::Migration
def self.up
create_table cars do |t|
t.column :name, :string
t.column :manufacturer_id, :integer
end
end

class Manufacturer < ActiveRecord::Base
has_many :cars
end

class CreateManufacturers < ActiveRecord::Migration
def self.up
create_table maufacturers do |t|
t.column :name, :string
end
end

Now, I need a form to create new Cars that has two text fields: name,
and manufacturer. I can’t use a select for manufacturer, because there
are far too many of them (let’s pretend). What I can’t figure out is
how to construct the text_field helper tag in my form such that Rails
understands that the form field doesn’t map directly to a field in the
Car object, but rather to the name field of the car’s Manufacturer
object. Is there even a way to do it? I’m looking for something like
one of these (neither of which work, obviously, but they may help to
clarify what I’m trying to do):

<%= text_field ‘car’, ‘car.manufacturer.name’ %> or
<%= text_field ‘car’, ‘car.manufacturer[:name]’ %>

Without the ability to do that, I’m not sure how I could have - for
example - an edit form without writing special code to populate that
field, or how any of the validates_* methods would work. I’ve tried
using fields_for, but it doesn’t work; probably because I’m not doing
it right. Maybe someone knows how to use fields_for to accomplish the
above? I think what I tried was something like this:

<% fields_for :manufacturer, @car.manufacturer do |m_field| %>
<%= m_field.text_field :name %>
<% end %>


Bill K.


#2

One thing you can do is define a pair of methods on the car object
something like this (off the top of my head).

def manufacturer_name=(value)
manufacturer.create(:name => value)
end

def manufacturer_name
manufacturer.name
end


#3

On May 19, 6:44 pm, dasil003 removed_email_address@domain.invalid wrote:

One thing you can do is define a pair of methods on the car object
something like this (off the top of my head).

def manufacturer_name=(value)
manufacturer.create(:name => value)
end

def manufacturer_name
manufacturer.name
end

Won’t manufacturer.create store a new manufacturer in the
manufacturers table? In my case, they’re all pre-defined. Users
populating this form aren’t creating a new one, they’re typing the
name of one that should already exist, after which I validate.

But on that note, I did try something like this:

def manufacturer=(m)
if m.instance_of? String
self.manufacturer = Manufacturer.find_by_name(m)
else
self.manufacturer = m
end
end

Of course, this resulted in an endless loop. Woops.

-Bill K.


#4

On May 19, 7:30 pm, Bill K. removed_email_address@domain.invalid wrote:

manufacturer.name
end

Won’t manufacturer.create store a new manufacturer in the
manufacturers table? In my case, they’re all pre-defined.

Actually, you’ve pretty much nailed it. I set my form up like:

<%= text_field_for ‘car’, ‘manufacturer_name’ %>

And in Car:

def manufacturer_name=(m)
self.manufacturer = Manufacturer.find_by_name(m)
end

def manufacturer_name
self.manufacturer.name
end

This seems to do pretty much exactly what I was trying to accomplish,
and my validates_presence_of works. The only thing that doesn’t work
is validates_associated :manufacturer, because when an invalid
manufacturer name is entered it isn’t found in the database, so
manufacturer remains nil and the validates_presence_of fails instead.
But I can live with that.

Thanks for the brain kick. :slight_smile:

-Bill