Complex has_many :through associations in Rails
has_many :through
associations can get a bit complicated when they involve self-referential relationships. Let’s take Twitter as an example to state this problem. User A follows users B and C, but not D. This is represented by the Follow
model. Each User also has may tweets.
We now need to define an association followed_tweets
on users such that a.followed_tweets
will return all the tweets by users B and C, but not the ones by D.
In migrations:
Before we can define the followed_tweets
relation on User, we must first define a followed_tweets
relation on Follow.
Now we can use follow.followed_tweets
instead of follow.followed_user.tweets
. This also means that we can write a has_many :followed_tweets, through: :follows
relation on the User model.
Here’s what the relations look like now:
Here’s a blog post that clearly explains self-referential has_many :through
associations. (Warning: the examples are from Rails 2.0.) In our example, that would be the association representing a user having many followers or followed_users.
However, we have explored this to one more level, ie. a has_many :through
association where the “through” attribute indirectly references the same model (User) as the source.