has_many :through polymorphic with STI
Friday, September 5th, 2008The code for has_many :through polymorphic is pretty straightforward but what if you are using Single Table Inheritance (STI) on either or both sides of the polymorphic through table?
There were a number of painful hacks to make this work until a patch to ActiveRecord by Trevor Squires added the :source_type key to has_many :through polymorphic (hmtp). Check it out here: [PATCH] allow polymorphic :source for has_many :through
The main purpose of this blog post is to write up an example of using :source_type in the hope that people won’t get tripped up by out-of-date blog posts which delt with hmtp before the :source_type patch.
The Scenario:
Your web application has Users and Organizations and users belong to an organization through Memberships.
This is a typical example of where you might use has_many :through. But what if you have many subclasses of users - like Student and Admin - and/or you have subclasses of Organizations - like StudentOrganization and AthleticTeam. To make this work you’ll need the :source_type key. Once you have that it’s quite simple:
The Key Models:
class User < ActiveRecord::Base
has_many :memberships
has_many :organizations, :through => :memberships, :source => :member_of, :source_type => 'Organization'
end
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :member_of, :polymorphic => true
end
class Organization < ActiveRecord::Base
has_many :memberships, :as => :member_of
has_many :users, :through => :memberships
end
The Other Models:
class Student < User
end
class Admin < User
end
class StudentOrganization < Organization
end
class AthleticTeam < Organization
end
