# STI, polymorphism and base\_class?

**URL:** <https://www.ruby-forum.com/t/sti-polymorphism-and-base-class/143309>\
**Category:** Rails\
**Created:** [July 17, 2008, 7:03am UTC](https://www.ruby-forum.com/t/sti-polymorphism-and-base-class/143309 "2008-07-17T07:03:53Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [July 17, 2008, 7:03am UTC](https://www.ruby-forum.com/t/sti-polymorphism-and-base-class/143309/1 "2008-07-17T07:03:53Z")

</div>

So a while back, I stumbled over here:  
[http://dev.rubyonrails.org/ticket/8841](http://dev.rubyonrails.org/ticket/8841)

Turns out I was having problems because what seemed to me a bug: with  
a polymorphic relationship that also uses STI, Rails stores the type  
field as the base class, not as the STI child class.

I can see the argument that this is “right” because that’s where the  
table name comes from. But here’s my major problem: if you don’t store  
the actual STI class, how can you possibly recreate it? You can always  
go down the chain, but can’t go up. I.e. a child class can use  
class.base\_class to get the base, but if you are at the base class,  
you can’t “infer” the proper child class.

For example, in Pratik’s example here: [http://pastie.org/75480](http://pastie.org/75480) if you  
set up that code (with DB tables), then do:

video = Video.create  
attachment = Attachment.create  
video.attachment = attachment

The “attachable\_type” field in the “attachments” table is: “Asset”,  
and not “Video”.

So later, if you do:

Attachment.find(x).attachable # =\> Asset(…)

I.e. it returns an Asset object, and NOT a Video object.

I just tried this in Rails 2.1.0.

I’m trying to figure out if I’m missing something or if there is  
legitimately a concern here. Wouldn’t you want to store “Video” for  
“attachable\_type”? What is the argument for storing “Asset”?

And it gets really messy for me because I have some code where the  
base class is abstract. The subclasses using STI each have their own  
table. So in Pratik’s example, Asset wouldn’t have an “assets” table.  
But there’d be a “photos” table, for example. And without getting the  
right class in the “attachable\_type” field, you get SQL errors for non-  
existent tables.

Can anyone help shed some light on this? Or do I need to continue the  
monkeypatching I did with Rails 2.0.2 (which is when I discovered  
this)

Thanks!

-Danimal

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [July 17, 2008, 7:20am UTC](https://www.ruby-forum.com/t/sti-polymorphism-and-base-class/143309/2 "2008-07-17T07:20:54Z")

</div>

Yikes! Replying to my own post!

Well, I did some more banging around. _sheepish grin_

It looks like it will set the child class if the base class is  
abstract.

Also, if you set a “type” field on the base class’ table (if it’s not  
abstract), it will set that to the type and use that.

So, apparently, I just wasn’t understanding exactly how to set this up  
right.

Yay Rails!

Just in case my voluminous time spent on this might be useful to  
someone else. Here’s a quick summary:

1. If you want to store the base class on the polymorphic table (but  
why would you?), leave off the extra “type” field on the STI table.

2. If you want to store the inherited type on the polymorphic table,  
add in a “type” (string) field on the STI table.

3. If you want to use child tables and leave the parent base class as  
tableless, you need to:  
a) explicitly set the base class’ model to be abstract:  
self.abstract\_class = true  
b) explicitly set the child class’ model to use a different table:  
set\_table\_name :photos

Ok. Good. I can toss out my monkeypatching. Whew!

-Danimal

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [August 15, 2008, 9:56pm UTC](https://www.ruby-forum.com/t/sti-polymorphism-and-base-class/143309/3 "2008-08-15T21:56:49Z")

</div>

can u give an overview of ure table fields? i am trying to do  
something similar but im not really sure how to go about it!

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [February 19, 2009, 9:18pm UTC](https://www.ruby-forum.com/t/sti-polymorphism-and-base-class/143309/4 "2009-02-19T21:18:05Z")

</div>

I’m having the same issue regarding polymorphism and STI. #2 below  
didn’t work for me however. At this time I don’t have a (good)  
solution.

Danimal wrote:

> 1. If you want to store the inherited type on the polymorphic table,  
> add in a “type” (string) field on the STI table.
