I've found a bunch of articles, stackoverflow answers and rails documentation about 'source:', but none of it explains this association in a way I can understand it. I need the most simplified explanation of this way of associating, if possible.
My example is this:
Album:
has_many :reviews, :dependent => :destroy
has_many :reviewers, through: :reviews, source: :user
belongs_to :user
Review:
belongs_to :album, optional: true
belongs_to :user
User:
has_many :reviews
has_many :reviewed_albums, through: :reviews, source: :album
has_many :albums
The rest of the code does not mention "reviewers" or "reviewed_albums", so that is the part I understand the least.
Are those names completely irrelevant?
Association in Rails defines the relationship between models. It is also the connection between two Active Record models. To figure out the relationship between models, we have to determine the types of relationship. Whether it; belongs_to, has_many, has_one, has_one:through, has_and_belongs_to_many.
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.
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.
TL;DR
source
is standing for the table that this association is referring to, since we give it a different name than just .users
because we already have the belongs_to :user
association.
Long explanation
I think it's easiest with this little picture which is basically the database schema for the models you posted above.
We have albums, that belong to users, meaning that a user is basically someone who creates an album. We also have reviews and they belong to albums, meaning an album can be reviewed. And a review is made by a user so that's why a review belongs to a user.
Now associations in rails is a way to create methods that can be called on a database record to find its associated record.
We could get a user from an album or all the reviews a user made for example.
album = Album.find(1)
album.user # => returns the creator of the album
user = User.first
user.reviews # => returns all the reviews a user made
Now there is even more connections between those models than the ones mentioned above.
Let's look at album first:
# album.rb
has_many :reviews, :dependent => :destroy
belongs_to :user
has_many :reviewers, through: :reviews, source: :user
An album belongs to one user who created it. It has many reviews. And, if we we follow the line from albums to reviews and then further along to the users table, we see that we can also access the users that gave the reviews. So we would want to do something like
album.reviews.users
Meaning: give me all the users that left a review for this album. Now this line of code wouldn't work - because album.reviews
returns an array (an ActiveRecord::Relation object to be exact) and we cannot just call .users
on this.
But we can have another association
has_many :reviewers, through: :reviews, source: :user
And here we're calling it reviewers
to not get confused with the method/association .user
that refers to the creator. Normally, Rails would refer the database table name from the name of the association. Since we're giving a different name here, we have to explicitly give the name of the DB table we're referring to and that is the users table.
So this is what this line is about - we create another association, we don't want the direct line (see image) between album and user, we want the users that left a review on this album, so we go through
the reviews table and then we have to give the name (source
) of the table so Rails knows in which table to look.
And this will finally allow us to write code like this:
album = Album.first
album.user # => creator of the album
album.reviewers # => all users that have left a review for this album
Hope that helps! Let me know if you have any more questions. Maybe you can explain the other association with source in the users model in the comments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With