views:

95

answers:

2

I'm building out an Answer ActiveRecord class that can have different types of answers. That is, the answer could be an integer, float, date, string... whatever...

The way I see it there are two ways to store the answers

1)

Have an attribute named "value" that is serialized.

This is nice since you can always access the answer from the same place. It probably sucks for searching answers since the data has to be de-serialized in order to be used (is this a correct assumption?)

2)

have several attributes integerValue, floatValue, etc...

This is easiest to search (if you know what type you're searching (which you probably do))

This sucks since the value isn't in the same place and need some hokey method like:

def value
  stringValue||floatValue||integerValue
end

and some validations to ensure that only the correct one is set

What would you do??

A: 

What converting the value to a string in the database. And using single table inheritance to define the type and retrieve the appropriate value.

You'd have one model Answer with two fields : one "value", which is a string.
And one "type", which is a string too and gets the type of the value.

Then for the float, you' have the following :

class FloatAnswer < Answer
    def value
        attributes['value'].to_f
    end
end

When you do a Answer.find(:all), if the element has FloatAnswer as value, you will have a FloatAnswer object. Not an Answer one.

So you keep only one database field and always have the datas in the appropriate format.

Damien MATHIEU
This is essentially the same as using 'serialize :value' and creates a searching nightmare since all the different data types are stored as strings... That is, how do I efficiently search for a given date (in the DB, not AR) if it's stored as s string??If I were going to STI I would probably have a different column for each data type and do something similar, like class FloatAnswer<Answer;def value;float_value;end;end
crankharder
+1  A: 

I'd do one of two things:

  1. Use single-table inheritance. Your table does contain those integerValue, floatValue, etc. fields; but it also contains a "type" field, and you'll subclass the Answer model to make IntegerAnswer, FloatAnswer, StringAnswer, etc. And then you can simply map the value accessor to one of those fields in each subclass. Look in the Agile book or Google on single-table inheritance in Rails for more on how to implement this.
  2. Use a non-relational database. Something like MongoDB or CouchDB would render this problem moot; you could make value anything you wanted, or have multiple values per answer, or skip it entirely. I personally like Mongo with the MongoMapper gem, and if I had to address your use case that's the direction I'd go. It is getting away from ActiveRecord and "mainstream" Rails though, so you'd have to be comfortable with living at least a little on the edge.
SFEley
yea, STI it is.
crankharder