

Full Stack
Engineering is about dividing problems into smaller partials. And then solving them with the best approach. As an engineer, I enjoy problem-solving.
In this article, you will learn how to create friendships on Rails. In the most basic form, this is far away from perfection. But totally working. You can find the GitHub repository link at the bottom of the page to dive deeper into the code. In the repository, you will also find very simple session management.
After reading this article you will have an understanding of friendships on Rails.
When you want to create a rails app with user friendship interaction, you have to decide what your final product will be. There are many different ways to form a friendship model. In this project we are choosing this model:
1. Users are allowed to send a friendship invitation to other users.
2. Users can accept or reject the invitation that is coming from another user.
3. Unfriending will delete the record
We will have a User model, and an Invitation model.
Letโs focus only on friendship details. The invitation model will have only three columns(by the way, keep in your mind that the Rails is always giving you 3 more columns by default: id as primary key, and 2 timestamps).
Those columns are: user_id, friend_id, and confirmed. user_id and friend_id are both referencing back to the users table(User model).
When I am sending an invitation to my friend: user_id will be my id and friend_id will be myโฆ well, you got that! And confirmed will be false by default.
This means an invitation is starting to wait to be accepted or rejected at the moment it got created. When the invitation is rejected, the row is gonna be deleted. When it is accepted the row is gonna be updated, confirmed: from false to true.
Any record with true value in the confirmed column means that those two ids are friends now.
Any record with a false value in the confirmed column means that user_id is waiting for friend_id to accept/reject his/her invitation.
Letโs run these three different commands on command line:
$ rails new friends4ever
$ rails g scaffold User name
$ rails g model Invitation user:references friend_id:integer confirmed:boolean
After this command we need to add
, default: :false
to our migration file. Right after this line:
t.boolean :confirmed
Letโs go to our model files, first: app>models>user.rb
Hold on there, I am explaining one by oneโฆ Our userย has many invitations. This means A user object will respond to the โinvitationsโ call.
User.first.invitations => should make sense
User.first.pending_invitations => should make sense
So what am I going to do with this call? On every usersโ page, I want to list the people who sent an invitation to that user. Very useful!
We have instance methods. And of course,ย we have a โfriendsโ method.ย This will return all the friends of a user in an array. I am not proud of what I do inside this method, but it is working ๐.
User.first.friends => should make sense (All the friends of the first user)
Inย theย โfriend_with?โ method,ย we are returning a boolean value.
User.first.friend_with?(User.last) => should make sense (Is the first user have a confirmed friendship with the last user?)
This is useful when you want to do things with the logic of friendship. For example, show the posts if they are friends, donโt show otherwise.
Withย theย โsend_invitationโ methodย we are sending invitations.
User.first.send_invitation(User.last) => should make sense (First user sending an invitation to the last user.)
With these very simple 5 interaction tool, we are done in the User model. Letโs go to the second one, the Invitation model.
app>models>invitation.rb
Nothing fancy, in 4 steps we will go through this.
Every invitation belongs to a user. Plain English. Very tasty. Haha! Long live DHH! ๐ Long live Matz! ๐
Invitation.first.user => should make sense(this will return a record, a user who sent the invitation to the other one)
After this point, as you realize, we have three class methods. Because I want them to be usable regardless of Invitation objects.
Starting withย the โreacted?โ methodย we are questioning if two of the given ids have any records in our table.
Invitation.reacted?(id1, id2) => should make sense
In some situations, you need to know this. For example, you want to show a button for an invitation and you have to know if the two ids have any record in the invitations table. If they have a record than you donโt want to show the button because now you know something. Those two users are in either of the following phases:
In both cases, we canโt create another record. So we are hiding our button with the information that is coming from this awesome method โ.reacted?โ.
Another class method isย the confirmed_record?(..).ย We are using this method in the User model. This method is basically checking a confirmed record for two given ids.
Invitation.confirmed_record?(id1, id2) => should make sense
The last method isย find_invitation(). We are using this method to find the invitation record of two given ids. Useful when deleting a confirmed relationship.
Invitation.find_invitation(id1, id2) => should make sense
Now we can run the migrations with:
rails db:migrate
And enter the rails console with:
rails c
You can create new users, send invitations, accept them with update methods, reject them with delete methods.
Furthermore, you can see the friends of a specific user, see the pending invitations, see the invitations that user sent, and more.
Well, I hope this helps you.
Keep in mind this is one of the many approaches.
There are more simple ones and more elaborate ones.
Previously published at https://medium.com/@kblycaglayan/how-to-create-the-simplest-friendship-model-on-rails-de0ab51448ec
Create your free account to unlock your custom reading experience.