# STI Problems

**URL:** <https://www.ruby-forum.com/t/sti-problems/125987>\
**Category:** Rails\
**Created:** [January 14, 2008, 1:43pm UTC](https://www.ruby-forum.com/t/sti-problems/125987 "2008-01-14T13:43:27Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![adish](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/848f3c/32.png) [@adish](https://www.ruby-forum.com/u/adish)\
**Post date:** [January 14, 2008, 1:43pm UTC](https://www.ruby-forum.com/t/sti-problems/125987/1 "2008-01-14T13:43:27Z")

</div>

Hi,  
I’ve been trying to figure out STI and I’m having some trouble  
getting things to work smoothly. I can generate the STI hierarchy with  
no problem but then things get strange.  
I ran an experiment to try and figure it out.  
Here’s what I did:

I try to create 2 completely scaffolded models, create a simple STI  
hierarchy between them (Son \< Parent) and see how Rails handles it.

At the command line:

```
ruby script\generate scaffold Parent name:string description:text
rake db:migrate
ruby script\generate scaffold Son member:string

```

Make 2 changes to the generated code:

1. Change the migration from creating a new sons table to adding 2  
new columns to the parents table:  
\* add\_column :parents, :member, :string  
\* add\_column :parents, :type, :string # needed for STI
2. Make Son (in app/models/son.rb) derive from Parent (instead of  
ActiveRecord::Base)

rake db:migrate again, and add a few Parents and a Son (through the  
console).

Result: At URL /parents all Parents and Sons are listed, since they  
are all saved in the same table. This is the desired behavior which  
would be expected with an is-a relationship between Sons and Parents.  
(Note that I use parent and son names in the parent i.e. base class  
and son i.e. derived class meaning and not in the genealogical sense)  
This view is generated by the scaffold generator script, and is  
actually app\views\parents\index.html.erb.

Since Sons are derived but different types from Parents it might be  
expected that the Show, Edit and Destroy links for actual concrete  
Sons will link to the (automatically generated) Son controller and the  
not to the Parent controller. This would essentially be equivalent to  
calling virtual methods.

This actually happens for the Show and Destroy links. However, the  
Edit link still redirects to the Parent edit page. The problem  
apparently stems from the Parent index view:

\<%= link\_to ‘Show’, parent %\>  
\<%= link\_to ‘Edit’, edit\_parent\_path(parent) %\>  
\<%= link\_to ‘Destroy’, parent, :confirm =\> ‘Are you sure?’, :method  
=\> :delete %\>

the edit\_parent\_path(parent) seems to be is not as smart as link\_to in  
detecting the STI hierarchy on the parent object.

Can anyone shed some light on this?  
What does link\_to do right that edit\_parent\_path does wrong?

There is a problem of consistency, either all actions (Show, Edit,  
Destroy) should point to Parent actions or they should all point to  
Son actions (this is arguable smarter and more in the spirit of  
Polymorphism). Having a mixed behavior is at best confusing.

Is it possible that the new RESTful helpers are “dumber” than link\_to  
or url\_for?

Interestingly enough, when I edit a Son object via the Parent edit  
view, the submit button actually calls Son’s update method!

Is there a away to simulate edit\_parent\_path() with link\_to in such a  
way to get consistent behavior?

Thanks,  
Adi

---

<div class="post-metadata">

**Author:** ![adish](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/848f3c/32.png) [@adish](https://www.ruby-forum.com/u/adish)\
**Post date:** [February 15, 2008, 2:34pm UTC](https://www.ruby-forum.com/t/sti-problems/125987/2 "2008-02-15T14:34:11Z")

</div>

Hi Adish,

I’ve actually faced the same problem this morning. Basically my models  
look like this

User \< ActiveRecord::Base  
then  
Administrator \< User,  
Lecturer \< User  
Student \< User.

I am using the same STI pattern with Rails 2.0.2.

In order to get the problems you’ve mentioned solved, for the “show”  
function, I used the following:

\<%= link\_to user.full\_name, user\_path(user) %\>

This would make sure that the link always refers to the parent.

Now about the destroy, I actually did not have a destroy link because  
I just needed the User to be suspended / unsuspended depending on the  
case. So I created those two methods in the UsersController (def  
suspend … end / def unsuspend … end).

And I tried the following:

\<%= link\_to ‘Suspend’, suspend\_user\_path(user), :confirm =\> ‘Are you  
sure?’, :method =\> :put %\>

Then I added the following in my “routes.rb”:

map.resources :users, :member =\> { :suspend =\> :put, :unsuspend  
=\> :put }

in your case, it’d probably be the following for the “routes.rb”:

map.resources :users, :member =\> { :destroy =\> :delete }

although I suspect Rails already has that implicitly defined.

The point is to note the difference between what you’d normally do for  
a destroy as in:

\<%= link\_to ‘Destroy’, parent, :confirm =\> ‘Are you sure?’, :method  
=\> :delete %\>

versus what was done for the “suspend/unsuspend” above.

This creates a consistency between the “show/edit/destroy/  
other\_methods” as I believe the edit\_parent\_path(parent) is the way  
it’s supposed to work.

I may be wrong on this but I hope this helps somehow.
