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?