How to follow yourself or implementing a ‘self join through’ relationship in rails API

Ed Putans
4 min readDec 3, 2018

--

Recently, during yet another Project week, I came across a challenge — my model required a many-to-many relationship…

…with itself! My model was similar to a typical social media application scenario: a user can follow multiple users, while another user can (but not necessarily will) follow this person back. Sounds easy enough, however both sides of the relationship happen to be the same model.

Now, there are resources online that teach you how to implement such a relationship, however I found that the documentation only confused me even more and the only other resources I could find were not easy enough to understand, especially when time constrained. To add salt to injury, it skipped the most important part about the explanation and did not show what the database should look like. This is what I would like to address in this post.

Implementing the relationship

To demonstrate the relationship, I am going to set up a Rails API. I will not attempt to be original and for the sake of better understanding and easier explanation I will use the same model as everyone else — a User can follow other users, who can follow other users.

If you are reading this, I will assume that you are able to create a rails application and I will not go into it. Instead, to set things off, let’s create the Follow model, which is a join class for our users.

/models/follow.rb

The above code tells our API, that the Follow belongs to a User class, but the sides of the relationship are going to be a Follower and a followed person, who we will call Followee. Both of the relationship models stem from the User model, which we specify in class_name.

/config/db/schema.rb

The snippet above, from our database, shows that our Follow model uses the IDs of the Follower and the Followee to store connections between users.

/models/user.rb

This looks a lot more complicated, so let’s go over it step by step.

has_many :follower_follows and has_many :followee_follows describes the way that follows connect to the user. The user has many follows, which apply to both the follower and the followee.

The foreign_key explains how the follower and followee are connected (similar to how SQL connects columns). In this case, the Followee has many Followers, which normally means, every Follower has to have a Followee id — the id of the person they are following. Since in our model a user can be both a followee and a follower, we store both.

class_name: “Follow” shows the application where to look for the connection, in this case — in the Follow class (Follow model — because Rails).

The next line, more specifically, has_many :followers, through: :follower_follows, explains in a typical Rails-y way that a user has many followers and the connecting class is the follow class. However, since we have both models of a Follower and a Followee, we need to explicitly tell it that.

source: follower / followee provides reference for the follower_id / followee_id within the database. More specifically which column withinFollow corresponds to which class.

Testing

I know that was a handful. Take your time to process it.

Done? Great. Let’s launch our console and test that everything works fine.
First, start by creating a couple users.

Created users ‘bob’ and ‘ed’

Next, let’s make Bob follow Ed (because Ed writes the best blog posts. Also Bob is his only friend)

Now, the moment of truth. If we check either one of the users, (after assigning them to variables) we will be able to see their relationship:

Ed has one follower and Bob has one Followee.

As you can see, Ed has a follower while Bob has a followee. Even though we have only 2 models — a user and a follow, they act as 4 different ones — 2 user models and 2 follow models.

Conclusion

Today we learned how to set a user likes many users who like many users relationship. Rails is quite a powerful tool and it allows us to set almost any relationship of models we can imagine. It does take effort to understand and implement such extraordinary relationships, though.

--

--

Ed Putans

Eastern European web developer sharing his thoughts of life and work in Western culture.