has_many :through polymorphic with STI in the polymorphic target tables
Hello, In our data model we have Users that can be members of Schools, Organizations, etc. The Schools table uses STI to support Colleges and High Schools,
The has_many code is pretty straightforward, here is the school side (school_memberships inherits from memberships): (all the models and schema at the bottom or Parked at Loopia)
class School < ActiveRecord::Base has_many :school_memberships, :as => :member has_many :users, :through => :school_memberships end
Now if I do:
some_school.users it runs the following query: SELECT users.* FROM users INNER JOIN memberships ON users.id = memberships.user_id WHERE ((memberships.member_type = 'School') AND (memberships.member_id = 3) AND ((memberships.type = 'SchoolMembership')))
The problem here is that there is no need for a memberships.member_type column, the memberships.type column is handling the polymorphism of the table. If I add this column in the migration anyway, it causes a problem because Rails doesn't populate it reliably (it populates it if you add a user to a school, but not if you add a school to a user -- some_user.schools << some_school).
My question, then, is how can I get Rails to not use the memberships.member_type column without overriding the built in methods?
I looked for people doing this and found some similar things: Josh Susser - has_many :through - The other side of polymorphic :through associations, and Pratik Naik - http://m.onkey.org/2007/8/14/excuse-me-wtf-is-polymorphs but they are focused on making polymorphism work at all (i.e. joining to multiple tables) and my problem seems to stem from having one of the target tables have STI on it.
Can anyone point me to where to look for anything on this, or to someone who has done it? Here's what works and does not work when I keep the membership_type column in more detail:
a_school.users << a_user it works perfectly and inserts a SchoolMembership into the memberships table #<SchoolMembership id: 1, user_id: 1, type: "SchoolMembership", member_id: 2, member_type: "School"> (in this case: #<User id: 1, name: "Joseph"> and #<College id: 2, name: "NYU", type: "College"> ) - here School puts "School" in member_type and "SchoolMembership" in the type
But, if I do: a_user.schools << a_school the SchoolMembership that gets created does not have a member_type: #<SchoolMembership id: 1, user_id: 1, type: "SchoolMembership", member_id: 2, member_type: nil> - User only puts "SchoolMembership" in the type
The Code:
class User < ActiveRecord::Base has_many :school_memberships has_many :schools, :through => :school_memberships end
class School < ActiveRecord::Base has_many :school_memberships, :as => :member has_many :users, :through => :school_memberships end
# Table name: schools