You know how some bug trackers (and other software) allow you to add custom fields?
Typically this is done with a data structure that looks something like this:
Items
----------
ID | NAME | ITEM_TYPE_ID
FieldDefinitions
---------------------------------------
ID | ITEM_TYPE_ID | FIELD_NAME | FIELD_TYPE
FieldValues
---------------------------------------
ID | FIELD_ID | ITEM_ID | VALUE
I'm trying to figure out the best way to approach this design in Rails. There will be many models which I want to allow extending simple properties.
When I retreive an Item
I'd like it to include a hash of the addition field values that have been defined for that model.
Something like...?
class Item < ActiveRecord::Base
has_many :field_values
has_many :field_definitions, :through => :field_values
def custom_fields_hash
cfh = {}
self.field_values.each |fv|
cfh[fv.field_definition] = fv
end
cfh
end
end
class FieldValue < ActiveRecord::Base
belongs_to :item
belongs_to :field_definition
end
class FieldDefinition < ActiveRecord::Base
has_many :field_values
has_many :items, :through => field_values
end
Or, you could change
cfh[fv.field_definition] = fv
...to...
cfh[fv.field_definition.field_name] = fv.value
Take a look at the Friendly ORM. It allows you to work with mysql without a schema. It was inspired by this blog post about how Friendfeed uses mysql to store schemaless data.
Friendly would replace ActiveRecord, although you can use ActiveRecord models next to Friendly models pretty easily.
If your intention is to have your FieldDefinition
records belonging to different models (for example, a column item_id
that points to either a SqueekyToyItem
or a BalloonItem
) then what you want is a polymorphic association.
It basically allows you to have an item_type
column (beside your item_id
column), which then specifies the actual type of item it points to.
There's a heading “Polymorphic associations” in the documentation for ActiveRecord::Associations::ClassMethods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With