I have a rails 3.1 project using devise for authentication.
I have several user types, each taking really remarkably different fields in the database. I had different models for each, but there was enough overlapping functionality between models such as messaging that it makes sense to have a single model. This was particularly an issue when dealing with messaging between users of different types.
Should I leave them all as individual table or move them into a single table? Multiple Table Inheritance really doesn’t make a lot of sense given the fact that we’ll be looking up users all the time. It would simply be too expensive join wise.
It just feels really dirty to have all the unused columns for each user type in the table.
Thought?
Personally I don’t think that unused columns are that much of a big deal, however if it really bothers you, you might want to try an unorthodox solution. Have you considered ‘bucketing’ all the attributes which aren’t common to your different types of users? I am talking about using a plugin such as attr_bucket.
Essentially you would add am extra column to you db table:
Then in each of your different user models (that inherit from a common class) you would have something like:
You would use the attributes just like they were defined in the normal way, but when you save the model into the database, all those attributes would be serialized via YAML and stored in the
:non_common_attributescolumn. When you load the model again, they will be transparently deserialized.There are some caveats, such as the fact that you don’t want to search for users via any of the bucketed attributes (since you can’t index on those attributes) etc. But in your case it may just be what you’re after. I wouldn’t worry too much about the cost of serializing and deserializing, it probably won’t be an issue since you’re unlikely to be saving/loading thousands of users at the same time.
Infact, I have used a similar solution (but hand rolled rather than using a gem), with a model where most attributes need to be encrypted. I just bucket all the attributes together and encrypt the bucket – works a treat.