has_one, has_many, habtm?

Let's suppose I'm designing an app for defining and storing
information about Widgets. Widgets have a number of properties. They
have a color, a shape, a size, a weight, a texture, etc. Each of these
properties is chosen from a pre-defined list of possibilities for that

My initial thought was that each property subclasses a parent property
(via STI):

class WidgetProperty < ActiveRecord::Base

Its migration self.up would look something like this:

create_table widget_properties do |t|
  t.column :value, :string
  t.column :type, :string

Presumably it's subclasses would all be along these lines:

class WidgetColor < WidgetProperty

class WidgetShape < WidgetProperty

. . . and so on. In the properties database, we'd have tables defining
properties such as:

:id => 1, :value => :blue, :type => 'WidgetColor'
:id => 2, :value => 'yellow', :type => 'WidgetColor'
. . .
:id => 36, :value => 'square', :type => 'WidgetShape'

There about two dozen different kinds of property, each with 6-8
values. But essentially they're all the same - just an id and a string
value. What I haven't yet figured out is the following:

1) Is STI really the way to go here? I'm not sure if it's buying me
anything or not.

2) In my Widget model class, should my Widgets "have_one
:widget_color, have_one :widget_shape" and so on, or should they
"have_many :widget_properties"? Or maybe they should
"has_and_belongs_to_many :widget_properties"?

Question 2 is where most of my confusion is. The properties aren't
really "things" themselves, they're just attributes that are assigned
to Widgets, and otherwise have no meaning. But many Widgets are going
to share properties (for example, there will be a lot of square, blue
Widgets), so the properties don't exactly belong to the Widgets.

I have a feeling there is probably a pretty straightforward way to do
this (since this situation isn't exactly unique, I'm sure), but for
whatever reason it isn't coming to me. I'm hoping someone can toss me
a lifeline here.

Thanks very much.

I see what you're saying. The catch, though, is that I also need to be
able to easily pull them out of the database to include them in forms
(as members of select lists, groups of radio buttons, etc.), so that's
kind of why they're going in their own table.

OK. So you know what colors, etc., will be the only possibilities ahead
of time?


Then why not this?

widgets(name, color_id, shape_id)

Color :has_many => :widgets
Shape :has_many => :widgets
Widget :belongs_to => :color, :shape

Then, collection_select for your selection lists, blue_color.widgets
for a list a of blue widgets, etc. Simpler, I think, than creating an
abstract class called WidgetProperty.

It is a bit simpler, but it also means I'll have a couple dozen tables
with 6-8 rows in them. It isn't a tragedy, but it seems a bit less
than optimal. What about a combined approach:

class WidgetProperty < ActiveRecord::Base

create_table :widget_properties do |t|
  t.column :value, :string
  t.column :type, :string

class Color < WidgetProperty

class Shape < WidgetProperty

Color :has_many => :widgets
Shape :has_many => :widgets
Widget :belongs_to => :color, :shape

I think then I can use a single table for all of my properties. Or am
I missing something? Not having used STI before, I'm not sure if
ActiveRecord will know that it needs to look in the widget_properties
table to find a Color or not. I suppose I could try it and find out.

Thanks for your advice so far.