Making a Follow/Unfollow Button in Rails

Carla Stickler
From the Stage to the (Computer) Screen
6 min readJun 24, 2019

Ok, so you’ve decided to build some sort of social aspect to your new website and you think to yourself, hey, I should have a way for users to follow other users. I see that Instagram has that feature, and so does Facebook, I mean, it’s everywhere, how hard can it be to make! You do some digging on the internet and you start finding things about self referential tables and your brain starts to explode cuz you just figured out how has_many_through relationships work and now you have to do what???

BUT WAIT! You can do this! Self referential tables are pretty awesome once you wrap your brain around them. This guy, Dick Ward, wrote a pretty great Medium article on how to create the follower/followee relationship. So, before you continue with this article, I recommend reading his:

Thank you Dick!

Now that you’ve got your tables and relationships all built out, let’s move on to building that follow and unfollow button!

Let’s start with creating our routes, because yes, it’s time you learn to love custom routes. You will need to create two custom routes for this button to work.

post '/users/:id/follow', to: "users#follow", as: "follow_user"post '/users/:id/unfollow', to: "users#unfollow", as: "unfollow_user"

Notice that we are using the HTTP verb ‘Post’ for these routes. These routes are similar to when we use update or create on a user’s profile. We are posting the change behind the scenes in the method we will create in our UsersController. Similar to when we edit a particular user, we want to make sure that our path recognizes which user we are trying to follow by putting their id in the path after ‘/users/’. And since we are calling this ‘follow’ or ‘unfollow’, we can finish out the route with which ever action we want to take here. The third part of this custom route will direct the route to the method we are creating in the UsersController to make the magic happen. So we must make sure we create a method called #follow and #unfollow. The final and optional piece to this route is the alias at the end. I like to make my code easy to read so I want to be able to call on these routes in my code using “follow_user” instead of having to write out the entire path with all those slashes and quotes.

You still with me?

GREAT! So next let’s build out our methods in our UsersController. You’re going to need two methods here.

class UsersController < ApplicationController  def follow
@user = User.find(params[:id])
@current_user.followees << @user
redirect_to user_path(@user)
end
def unfollow
@user = User.find(params[:id])
@current_user.followed_users.find_by(followee_id:
@user.id).destroy
redirect_to user_path(@user)
end
end

There are few things I want you to notice here , we have an @user and an @current_user. @user refers to the person who’s page the @current_user is visiting. If you have set up your authorizations correctly you should be able to call on @current_user throughout all of your controllers and their corresponding methods. For the purpose of this article, I’m not going to go into how authorizations work in Rails. But this guy, Stefan Wintermeyer, wrote a great Medium article about it and I recommend you looking at it if you don’t understand how cookies and sessions work in Rails.

Just to give you reference for my code, my ApplicationController looks like this:

class ApplicationController < ActionController::Base
before_action :session_user
before_action :authorized?

def session_user
@user_id = session[:user_id]
@logged_in = !!@user_id
if @logged_in
@current_user = User.find(@user_id)
end
end
def authorized?
unless @logged_in
return redirect_to login_path
end
end
def logout
session[:user_id] = nil
end
end

OK, back to that UsersController. The follow method is pretty self explanatory. You’ve got to find the user who’s page your on, and save it to @user. Then you need to create a new instance of your follow by connecting the @user and the @current_user. You are going to shovel the @user into the @current_user’s list of followees. And once this is done, you want to redirect back to the page you are currently on, the users_path(@user).

The unfollow method is slightly more complicated. You have to locate the person who’s page your on and store them into @user just like in the follow method. But this time, we need to match that user with one that is in the list of followees of our @current_user.

@current_user.followed_users.find_by(followee_id: @user.id).destroy

So we need to search through the @current_user’s list of followed_users (which we set up when we created the relationships in our models) and find the @user.id that matches the followee_id in the last list. Then we .destroy and blamo, obliterated!

Don’t forget to reroute back to the users_path after you destroy the follow relationship between the two users.

Great, so we’ve got our routes and our controller all ready to go, but so far we have nothing on our page to make any of this happen.

Let’s go to our user’s show page and get those button’s made. I’ve got the following code in app/views/users/show.html.erb:

<% if @current_user == @user %>   <h5><%= "#{@current_user.username}'s page" %></h5><% elsif @current_user.followees.include?(@user) %>   <h5><%= button_to "UnFollow #{@user.username}",     
unfollow_user_path, method: "POST" %></h5>
<% else %> <h5><%= button_to "Follow #{@user.username}", follow_user_path,
method: "POST" %></h5>
<% end %>

There are three things going on here. The first is stating that if we are on the @current_user’s show page (the user who is logged in to the app at the moment) let’s just have it say that the page belongs to them. We don’t need a follow/unfollow button on our own personal page.

The second part is our unfollow button. If the @current_users’s list of followees includes the @user (the user who’s page we are visiting), then we show them a button that says “UnFollow #{@user.username}” or “UnFollow Susan”.

The third part says if they aren’t the @current_user or the part of their followees, let’s show the “Follow” button.

So, now that we got that out of the way, let’s talk about what those buttons are doing. Rails gives us button_to which makes making buttons pretty easy. The first part tells us what the button should say, so in our case it’s either “Follow” or “UnFollow”. The second part is the route that connects to that custom route we created earlier. Remember when I said I like to create aliases so I don’t have to put the entire route down, that’s where that alias goes, with the word ‘path’ after it. The last bit is the method we need to tell this button to execute. By default, button_to will create a “post” method. I like to add it in just for my own clarity, but it isn’t necessary. If this were a button to delete, you’d have to specify the method as ‘delete’, same if we were creating a search bar which is a ‘get’ method.

And just like that, we did it! We made some magic with Rails and created a follow and unfollow button. Congratulations!!

--

--