# STI functionality, but then with multiple tables

**URL:** <https://www.ruby-forum.com/t/sti-functionality-but-then-with-multiple-tables/111140>\
**Category:** Rails\
**Created:** [August 3, 2007, 12:10am UTC](https://www.ruby-forum.com/t/sti-functionality-but-then-with-multiple-tables/111140 "2007-08-03T00:10:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![daxhuiberts](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/977dab/32.png) [@daxhuiberts](https://www.ruby-forum.com/u/daxhuiberts)\
**Post date:** [August 3, 2007, 12:10am UTC](https://www.ruby-forum.com/t/sti-functionality-but-then-with-multiple-tables/111140/1 "2007-08-03T00:10:56Z")

</div>

Hello,

I’m creating my own Tumblr [[tumblr.com](http://tumblr.com)] like rails app.  
It’s like a blog, but in this case a blog post could be of a certain  
type, i.e. a regular post, a video, a link, a photo, a song(info).  
Well now, it’s clear that they share a lot of similar functionality:  
title, created\_at/updated\_at, commentable, probably has an author\_id,  
etc…  
But besides that they are very different: a post has a large text field,  
a link has an url and a description and a photo a reference to the file  
in a way.

What to choose? Single Table Inheritance? Not really an option since the  
post types are very different.  
A polymorphic relation mabye, with a Post; has\_one :subtype,  
:polymorphic =\> true;  
And that’s what I did, but soon enough I saw that it gave me a lot of  
problems.  
First of all, it’s not really a subtype, in this case :subtype is really  
a child model. When I have a post of type link, I would access the title  
through @post.title, but the url and description through  
@post.subtype.url and @post.subtype.description accordingly.  
Not really nice, but with some nifty method\_missing handler I made it a  
bit easier.  
Now when I only want to have posts of type link I could do Link.find and  
I would have only links. But that one behaves so much different from  
working from Post as in this case I would read the attributes like  
@link.url, @link.description, @link.post.title  
Not very consistent, at all.  
So I use Post.find :all, :conditions =\> {:subtype\_type (bad naming, I  
know) =\> ‘Link’  
To ease that I made a custom find method to accept Post.find :all, :type  
=\> :link and all was happy.

Sorry for the long post, it’s been on my mind for such a long time  
already.  
Anyways…

I was very proud on how I got it to work. Only instead of a Link.find  
:all I had to do a Post.find :all, :type =\> :link, and most was based  
around that. I could accept that, even though it was hard give up to. It  
required some more hacking to enable easier Post creation of a certain  
type and made my Post class bits by bits uglier to make it ‘easier’ to  
work with.

But then after a while I wanted to add a relationship to Artist with  
post of type song.  
But how!?! I couldn’t just link the relationship between Artist and  
Song, as that would mean would have the same effect as before. That I  
don’t get posts of type Song, but pure song models instead, with all the  
incosistent use as before.  
And a relation between Artist and Post where the foreign key lies in  
Song is not possible in rails. And I thought by myself “who the fuck  
wants to make such a complex database model, the eediot!!”  
At this moment I KNEW this is a flawed model too! And I’ve been thinking  
and wandering and whining and crying since then. Not knowing how to  
elegantly solve this stupid problem of mine.

STI in rails works really nice! It wouldn’t have any of these problems I  
just described above, so why can’t I make how STI models in rails work  
using multiple tables. That would be really nice and I believe this  
would actually be a feasible.  
the Post table would be the same as with a STI model (id, title,  
created\_at, updated\_at, title, type) but the subtypes with have their  
own table, the links table would look something like (post\_id, url,  
description) and the songs table something like (post\_id, artist\_id,  
…).  
The subtypes don’t need an id column, as they don’t, won’t and shouldn’t  
be models themselves.  
As with polymorphic relations, eager load is not an option. I can’t load  
the url and description info from the links table as I don’t know what  
type the post will be at query time. Well, has\_many\_polymorphs  
[[Evan Weaver](http://blog.evanweaver.com/pages/has_many_polymorphs)] has some nice magic on  
this as long as you know (define) what subtypes there are. But even  
then, without eager loading I would be quite happy.

## Quite happy? I will probably jump for joy!! Thank you for reading, how are your thoughts on this?

Dax H.

---

<div class="post-metadata">

**Author:** ![daxhuiberts](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/977dab/32.png) [@daxhuiberts](https://www.ruby-forum.com/u/daxhuiberts)\
**Post date:** [August 3, 2007, 2:47am UTC](https://www.ruby-forum.com/t/sti-functionality-but-then-with-multiple-tables/111140/2 "2007-08-03T02:47:39Z")

</div>

Dax,

I am writing something similar (well, its an app using polymorphism  
whose objective is to have many different objects be published and  
search consistently). I’m not saying I have an answer for you, but I  
can describe my approach. In my case the basic objects are Article  
which is associated with Story, Map, Gallery and Image. I also have a  
design goal to be able to add new objects easily.

I’ve done two things which ease the burden a little:

1. I created a module I mixin to each sub-type object. In this  
module I have accessor methods for basically all the main object  
attributes. For example, the module defines article\_headline,  
article\_tags, article\_author and so on. These now appear as  
attributes in each sub-type. I order to facilitate publishing i ensure  
each sub-type has a unique “name” attribute and a “description”  
attribute. These are the only two assumptions I make but it lets me  
abstract the publishing model pretty easily.

2. I created a controller called ArticleController which implements  
the CRUD loop and other common functions. Then I inherit from that  
controller for the controllers for my objects.

It doesn’t solve all problems by any means. But it does mean I can  
search for Articles by author, name, tags, posting/update dates  
irrespective of what sub-type. I can invoke a show/edit/new function  
on any sub-type without knowing its type and get the right behaviour.

And I can add a new object in less than an hour (if its a basic  
object). I create the model and controller as usual and create the  
views for show and edit. Add the “require” and “include” for the  
mixin in the model. Change the inheritance in the controller. All  
done.

Probably not general interest to the list, so email me as kipcole9 -  
at- gm-ail dot com if you’d like to continue the conversation - i’d  
like to find a more elegant solution to this too.

Cheers, --Kip

On Aug 3, 6:10 am, Dax H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![daxhuiberts](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/977dab/32.png) [@daxhuiberts](https://www.ruby-forum.com/u/daxhuiberts)\
**Post date:** [August 3, 2007, 9:26am UTC](https://www.ruby-forum.com/t/sti-functionality-but-then-with-multiple-tables/111140/3 "2007-08-03T09:26:26Z")

</div>

Hey Kip,

Yes, I am familiar with this approach too.  
I use it for a different project and it’s actually the nicest sollution  
so far.  
And with the power of has\_many\_polymorphs I have everything I ever need.  
One minor detail is that I don’t use a module with the generic  
functionality, but I use an abstract base class, which eventually works  
exactly the same.

The only one thing I’m missing here is to get the 10 latest posts (like  
Tumblr again) of each kind. This way I have to do a find 10 on each  
individual post type, ordered by creation date, concatenade them all,  
sort them by the same ‘order by’, creatoin\_date that is, and use only  
the top 10 of that list.  
Now imagine this method with pagination and WHAM! It’s not cool anymore.  
Now get the 20 latest posts of each kind, concatenade them, sort them,  
and take the 2nd 10 from the beginning. Not cool at all!  
Not that I want to do pagination all the time, I’d rather make  
subselections for each month, but even then, pagination is still an  
option.

I don’t have to do this with my other project, so this method works  
great, but for my Tumblr like project, it doesn’t solve it either.

Thanks for reading, Dax.

PS: I wonder how 37signals does this with basecamp and backpack, they  
sorta do the same thing I’d like to do.

Kip wrote:

> Dax,
> 
> I am writing something similar (well, its an app using polymorphism  
> whose objective is to have many different objects be published and  
> search consistently). I’m not saying I have an answer for you, but I  
> can describe my approach. In my case the basic objects are Article  
> which is associated with Story, Map, Gallery and Image. I also have a  
> design goal to be able to add new objects easily.
> 
> …
