9

In ActiveRecord, has_many :through, and Polymorphic Associations, the OP's example requests ignoring the possible superclass of Alien and Person (SentientBeing). This is where my question lies.

class Widget < ActiveRecord::Base
  has_many :widget_groupings

  has_many :people, :through => :widget_groupings, :source => :person, :source_type => 'Person'
  has_many :aliens, :through => :widget_groupings, :source => :alien, :source_type => 'Alien'
end

SentientBeing < ActiveRecord::Base
  has_many :widget_groupings, :as => grouper
  has_many :widgets, :through => :widget_groupings
end


class Person < SentientBeing
end

class Alien < SentientBeing
end

In this modified example the grouper_type value for Alien and Person are now both stored by Rails as SentientBeing (Rails seeks out the base class for this grouper_type value).

What is the proper way to modify the has_many's in Widget to filter by type in such a case? I want to be able to do Widget.find(n).people and Widget.find(n).aliens, but currently both of these methods (.people and .aliens) return empty set [] because grouper_type is always SentientBeing.

Community
  • 1
  • 1
deefour
  • 34,974
  • 7
  • 97
  • 90
  • This question is very similar to one [I posted earlier][1]. It's an interesting problem because, like you said, the `grouper_type` attribute only stores the superclass. It seems that what is needed is a join between the widgets and sentient_beings tables. A more long-winded query like the one I used would probably work for you, but it's not pretty - hence the reason I asked my question. [1]: http://stackoverflow.com/questions/6582588/rails-structuring-a-query-involving-a-polymorphic-association-and-sti – JamesDS Jul 05 '11 at 19:19
  • <3 anonymous down-votes. – deefour Feb 01 '13 at 18:06

1 Answers1

13

Have you tried the simplest thing - adding :conditions to the has_many :throughs?

In other words, something like this (in widget.rb):

has_many :people, :through => :widget_groupings, :conditions => { :type => 'Person' }, :source => :grouper, :source_type => 'SentientBeing'
has_many :aliens, :through => :widget_groupings, :conditions => { :type => 'Alien' }, :source => :grouper, :source_type => 'SentientBeing'

JamesDS is correct that a join is needed - but it's not written out here, since the has_many :through association is already doing it.

Matt Jones
  • 544
  • 3
  • 5