How to Create a Follow/Unfollow Feature in your Rails Social Media Application

Using Self-Referential Relationships to Add Meaningful Interactivity to your App

Hannah Kofkin
Level Up Coding

--

Photo by George Pagan III on Unsplash

Have you ever wondered how social media platforms such as Twitter, Instagram, and Facebook implemented a function to follow and unfollow other users? While building a social media app, I struggled with this for a long time, and thanks to a couple very helpful blogs, along with my amazing teammate (shoutout Aleksa!), I was able to build both features! And the best part is, it was not as difficult as it seemed.

Before getting into details, here’s a summary of the process:

  1. Create a User model with desired attributes
  2. Create a Follow model to act as joiner with foreign keys
  3. Create relationships in each model, referring to the corresponding class (this is what makes it self-referential)
  4. Set up custom routes for a follow and an unfollow
  5. Write follow and unfollow methods within the User model
  6. Create follow and unfollow buttons

Please note: The outlined process below requires prior setup of the session and authentication. This setup will ensure you can reference the current user as I do in my walkthrough below. Here is an awesome article detailing this setup process.
Simple Authentication Guide with Ruby on Rails by Rei Reynoso

STEP 1: SETTING UP THE SELF-REFERENTIAL RELATIONSHIP

Once your new rails app has been generated using rails new file-name, it’s time to create the models. This walkthrough is very simple, only stepping through the base requirements to make this feature work.

First, the user model and controller need to be generated. A quick way to do this in the terminal is with the rails g resource command, chained with its attributes, like so:

rails g resource users name:string username:string location:string bio:string

The attributes can be customized based on your needs, this is just one example. Using the rails g resource command automatically creates a migration file for the users’ data. At this point, now that the model is set up, it helps to add a few test users in the console or to seed the data with some pre-loaded users. This is useful for the building and testing process.

Next, the joiner is created, which in this case will be the Follow model. This is where the self-referential relationship is established.

rails g resource follows follower_id:integer followee_id:integer

As shown, include two IDs — one for the follower, and one for the followee. To clarify, the follower is the person creating the follow and the followee is the person who is gaining that follower. This can be confusing, so a reminder is always helpful!

Now that the two models exist, it’s time to set the relationships to ensure everything connects. In the Follow model, add the belongs-to relationships for a follower and followee. By adding the class_name: ‘User’ to the end of the relationships, they become associated as sub-categories within the User class. It basically allows user IDs to be assigned to a follower and followee.

This code is located in app/models/follow.rb

The two validations in the above snippet are to ensure a user can only follow another user once and a user can only have one follow from another user.

In the User model, add the has_many relationships for a follower and followee. This one is a bit more complicated.

Let’s break this down:

has_many :followed_users, foreign_key: :follower_id, class_name: 'Follow'has_many :followees, through: :followed_users

The first line enables a user to follow many other users. It allows the foreign key follower_id to be accessed from the Follow class. The user’s ID can then be associated to the follow as the follower. The second line says that a user has many followees through the followed_users established in the line above.

has_many :following_users, foreign_key: :followee_id, class_name: 'Follow'has_many :followers, through: :following_users

This next piece is the same as above, just for the reverse relationship. A user can have many users follow them, and the followee_id can be used to associate a user’s ID to the follow as the followee. A user has many followers through the following_users established in the line above.

Please note: Also shown in the above snippet, I have several validations to ensure the user inputs correct information on the login page. These are very basic and in order to function properly it would be wise to add more, but that’s a separate topic and does not affect these follower-followee relationships.

That’s the end of the first step! You can now create follows in your console or seed data to connect two users through these follower and followee associations. Make sure to run rails db:migrate to migrate your tables and run rails db:seed if you pre-seeded data.

Another good blog to reference for this topic that we used when building our app is Dick Ward’s article about self-referential relationships.

STEP 2: SET UP THE ROUTES

Now that the models and relationships are set up, it’s time to create custom routes for a follow and unfollow.

This code is located in config/routes.rb

The POST action is used because this is similar to making a change or update to a user — the data is being updated by associating a follow to the follower and followee. There are three parts to this route. The first part includes /users/:id/follow, so when the follow button is clicked, you know which user it is associated with because of the ID in the URL — same idea for the unfollow route. The second part means when the button is clicked, the associated route will point to the follow or unfollow action defined within the Users Controller. The last part is optional, but allows the route to be more easily referenced in your code without needing to explicitly write the URL.

Based on the above, the next step will be to create the actions (or methods) within the Users Controller for a follow and an unfollow.

This code is located in app/controllers/users_controller.rb

For a follow, find the user, add that user to the current user’s followees, then redirect back to the user’s show page. We set a fallback location for our app, but this is optional.

For an unfollow, similarly, find the user, find the follow instance from within the current user’s followers, destroy the instance, then redirect back to the user’s show page.

Now that all this back-end work is set up, I recommend starting up the server while you add your code for the front-end. When you start to add page content with the buttons and play with the routes, it will be a lot easier to follow along step by step and test out your code as you go.

STEP 3: CREATE THE BUTTONS

All the connections and relationships are set up on the back-end. This step involves creating a front-end element a user can interact with to create and remove a follow instance.

This code is located in app/views/users/show.erb

In the user’s show page, simply create a section for the buttons and, within this section, add a conditional statement with a few different checks:

  1. If the user’s profile belongs to the current user, a ‘Logout’ button will be in the specified position — this is one option, but is not necessary depending on your desired layout
  2. Else if the current user is already following the user, an ‘Unfollow’ button will be in the specified position
  3. Else (meaning the current user is not following the user yet) a ‘Follow’ button will be in the specified position

In each of these options, a button_to element should be created to link to the desired path. This is where the follow_user and unfollow_user paths previously defined in the routes will be used.

My teammate and I added links to show a user’s followers and followees from their profile. This was an additional functionality that we wanted in our app because it’s beneficial to reference the list as follows are added or removed. Feel free to be creative and add any features you desire!

Below is an example of the follow and unfollow functionality from the app we built. As you can see, the ‘Follow’ button, once clicked, switches to the ‘Unfollow’ button. The follow was registered in the database, which is confirmed by the listing shown on the Followers page.

Example of how your button should function

Another great resource to reference while building this functionality is Carla Stickler’s article which walks through the follow and unfollow button process.

THAT’S IT!

Adding follow and unfollow functionality is as simple as that. At first it may seem daunting, but by setting up a couple models and routes, self-referential relationships can be used to easily create additional interactivity for users.

--

--