4
votes

I've just been reading Chad Fowler's blog post about 20 Rails Development No-Nos. On Single Table Inheritance he comments:

The storage of a column called “type” which holds a class name is a pretty good indicator that something fishy is going on. It’s fishy but not always bad. I think, though, that any time you use it you should ask yourself more than once if it’s the right solution. Databases don’t do what they do best as well when you have lots of STI and polymorphic associations.

I'm writing a blog application and I'm considering using STI for the comments that can be made on a post and for the contact messages that visitors can post if they want to get in touch with me. My Message model will inherit from my Comment model. They both share common attributes, except that Message will have an extra subject field. Another commonality is that both will be submitted to Akismet for spam checking.

Rather than just ask myself more than once if it's the right solution as Chad suggests, I thought I'd get some opinions from the Stack Overflow experts as well! Does what I'm proposing sound like a good fit for STI?

1

1 Answers

2
votes

I've used STI a number of times. Consider a CMS which might have Page, NewsItem, BlogItem etc.

They could each descend from a common class which in turn inherits from ActiveRecord. The table for each would be the same (title, body, tags, published_at) but each model might have different associations, or different statuses, or a different workflow so each has custom code in their own class. Yet they all share a common table and parent class. It also allow me to use the parent class to do a cross class search and have the resulting Array of records automatically type cast.

There are other ways to tackle this and maybe not the best example but there are certainly times when STI is handy for situations where object behavior may differ but persisted state is the same. Of course you have to be sure this is also true in the future.

In your case comments and contact messages are different. It sounds like there is there no benefit by having them in the same table. Maybe put shared code in a parent class or better still in a module in /lib.