Understanding :through => ... :source =>...

I'm trying to understand :through and :source with the following example.

I have a User, Job, and Interview models. An interview has an interviewer and interviewee. I would like to use the User model for this and I assume I would have to use :source. Any ideas on where to get started?

Where to start? Keep your user model simple. Think about what your views are going to show, and what the code should look like.

Interview   belongs_to :interviewer, :class_name => 'User'   belongs_to :interviewee, :class_name => 'User'

User   has_many :interviews

This gets tricky, does this join with interviewer_id or interviewee_id in interviews? You probably need two different names for these joins.

User   has_many :led_interviews, :class_name => 'Interview', :foreign_key => 'interviewer_id'   has_many :attended_interviews, :class_name => 'Interview', :foreign_key => 'interviewee_id'

I find it's best to write some sanity tests to confirm all this. I don't claim that this will work...

Now for the has_many :through join:

Job   has_many :interviews   has_many :interviewers, :through => :interviews   has_many :interviewees, :through => :interviews

This doesn't need a source, because it's going to look at Interview#interviewer or Interview#interviewee by default. Has_many :through associations are unique, they actually look at the other association (the "source" association) and use its reflection data. That's why there's no :class_name or :foreign_key option required. Here's a simple case where :source would be used:

Comment   belongs_to :user   belongs_to article

Article   has_many :comments   has_many :users, :through => :comments

In this case, you may not want to use #users. One: it may not be descriptive enough. Another reason is it may be too similar to Article#user, a belongs_to association pointing to the Article's author. So you can do this:

Article   has_many :comments   has_many :commenters, :through => :comments

Now you'll get some error about ActiveRecord not finding a #commenter or #commenters association on Comment. Of course, it's called #user instead!

Article   has_many :comments   has_many :commenters, :through => :comments, :source => :user

:class_name was just what I was looking for!

For anyone else interested in this, there is another short write up at