Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding :source option of has_one/has_many through of Rails

People also ask

How would you choose between Belongs_to and Has_one?

They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user . To determine who "has" the other object, look at where the foreign key is.

What is Rails polymorphic association?

Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.

What is self association in Rails?

Self-referential association means we create a JOIN MODEL, such as Friendship, for example, which links another model, such as User to itself, so a user can have many friends (which are other users), and a friend can be befriended by a user ( a follower and a followed).

What is Active Record in Ruby on Rails?

Active Record is the M in MVC - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database.


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.


Let me expand on that example:

class User
  has_many :subscriptions
  has_many :newsletters, :through => :subscriptions
end

class Newsletter
  has_many :subscriptions
  has_many :users, :through => :subscriptions
end

class Subscription
  belongs_to :newsletter
  belongs_to :user
end

With this code, you can do something like Newsletter.find(id).users to get a list of the newsletter's subscribers. But if you want to be clearer and be able to type Newsletter.find(id).subscribers instead, you must change the Newsletter class to this:

class Newsletter
  has_many :subscriptions
  has_many :subscribers, :through => :subscriptions, :source => :user
end

You are renaming the users association to subscribers. If you don't provide the :source, Rails will look for an association called subscriber in the Subscription class. You have to tell it to use the user association in the Subscription class to make the list of subscribers.


Most simple answer:

Is the name of the relationship in the table in the middle.