Self-Referential Association In Rails

Adam Adolfo
2 min readFeb 5, 2021

Social Media has become so prevalent in people’s everyday life. Most of these sites have some kind of relationship with users that creates the “social” aspect. Facebook uses friends, Twitter and Instagram is followers, LinkedIn uses connections. While I was working on my latest project for a friend I have come across the need to have a “friendship” feature.

Normally, in a many-to-many relationship we have a join table that connects two different models. Self-Referential in this context means that we want to create a many-to-many relationship between a table and itself. We want a User to have many friends, as well as that same User be friends of many other Users.

First we are going to want to create a table to act as the join. We will call this the Friendship model and we will need a friendships controller as well. It will need to keep track of two different ids: The instance of user initiating the request as user_id and the instance of user receiving the request as friend_id.

In the terminal:

rails g resource friendship user_id:integer friend_id:integer

We need to create some logic in the newly created friendships controller to handle creation of a friendship and deletion of a friendship.

Inside of friendships_controller.rb add a create and destroy method.

We then need to visit the models and create the association with the appropriate macros.

On the top of the Friendship model:

belongs_to :user

Rails won’t understand that friend is not a table here so we need to tell it that friend is actually a User.

belongs_to :friend, :class_name => “User”

On the top of the User model:

has_many :friendships
has_many :friends, :through => :friendships

No nicknaming anything is required here because rails knows what friends are now through friendships. At this point our program knows that there are users who can have many friendships as well as have many friends as a result of those friendships. The wording of these things can get confusing but for an example as a user I would have many friendships. Friendships would be the bond or container hold the proof I have a relationship with another person. Since I have many friendships I would also have to have many friends which would be the real life person I am friends with.

The last thing you would need to do would be to create a friendship. Begin by going to your friendships controller. Make a create function that will take in a user_id and a friend_id from whatever form you made and create a new instance.

def create
Friendship.create(
user_id: params[:user_id],
friend_id: params[friend_id]
)
end

At this point you can fire up the rails console (rails c in the terminal)and test this code out. Plug in some examples of your choice to the Friendship.create method. If everything worked you should be able to see the example.friendships as well as example.friends.

--

--