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.
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.