Understanding :source option of has_one/has_many through of Rails

Sometimes, you want to use different names for different associations. If the name you want to use for an association on the model isn’t the same as the assocation on the :through model, you can use :source to specify it.

I don’t think the above paragraph is much clearer than the one in the docs, so here’s an example. Let’s assume we have three models, Pet, Dog and Dog::Breed.

class Pet < ActiveRecord::Base
  has_many :dogs
end

class Dog < ActiveRecord::Base
  belongs_to :pet
  has_many :breeds
end

class Dog::Breed < ActiveRecord::Base
  belongs_to :dog
end

In this case, we’ve chosen to namespace the Dog::Breed, because we want to access Dog.find(123).breeds as a nice and convenient association.

Now, if we now want to create a has_many :dog_breeds, :through => :dogs association on Pet, we suddenly have a problem. Rails won’t be able to find a :dog_breeds association on Dog, so Rails can’t possibly know which Dog association you want to use. Enter :source:

class Pet < ActiveRecord::Base
  has_many :dogs
  has_many :dog_breeds, :through => :dogs, :source => :breeds
end

With :source, we’re telling Rails to look for an association called :breeds on the Dog model (as that’s the model used for :dogs), and use that.

Leave a Comment