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:
- 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 - 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