How to Create Following Relationships
Tags: ruby, devops, wecoded
Published: 2021-03-29 03:26:32

Creating an app is a process, and thinking of an idea worth implementing on its own can be a monumental task. But once that idea pops into your head, the idea you're very sure about, you're determined to make it appear just as beautifully on the screen. This, of course, is all easier said than done.
 
The time came to develop my first app, and I had this wonderful idea (the kind described above), but I had no *idea* how to implement it! Despite learning everything I needed to write the foundations of an app, I felt overwhelmed. To make things easier, I sat down and wrote on pen and paper the things I wanted for my app.

1. Users/profiles
2. Posts
3. Followers/following relationships

While this is only three things, it's three major things! Of course, my app has to have users, and it makes sense that those users would have posts. But following relationships? How could I do that. When I first looked at the words, I thought about using something like a hash or an array that would hold all the followers for a user. Although what I will make will be similar, a basic array or hash would be a very inefficient way of programming, only leaving problems for later. After learning ActiveRecord and Sinatra, I knew there had to be a better way. There was! Tables and table relationships.

After creating my users and posts tables/models, I created a follow model. My Follow class appeared as following:

```ruby

class Follow < ActiveRecord::Base
    belongs_to :follower, foreign_key: 'user_id', class_name: "User"
    belongs_to :following, foreign_key: 'following_id', class_name: "User"
end

```
So reading this, we could say that a 'follower' belongs to a follow (since you are following someone). Instead of creating a new table 'Follows', I assigned a foreign_key of 'user_id' to 'follower', joining to the User class. We would then read the next statement as a 'following' belongs to a follow (since that is the act of following another user), again with a foreign_key, but this time it is 'following_id' (the other user id), pulled from the User class. Creating this relationship with foreign keys cuts out the need to create and migrate a new table (not to say that it wouldn't need to be done in the future depending on what your app does).As confusing as it seems, after reading it over a couple times it will start to make sense!

But we're not finished yet! My User class also needed some adjustments to accommodate the new relationship. 
```ruby
has_many :follows

has_many :follower_relationships, foreign_key: :following_id, class_name: "Follow"
has_many :followers, through: :follower_relationships, source: :follower

has_many :following_relationships, foreign_key: :user_id, class_name: "Follow"
has_many :following, through: :following_relationships, source: :following

```
Since, the user will hopefully be following many accounts, it *has many* follows. Since it has many follows, it will also *has many* 'follower relationships', this is through the foreign key 'following_id' established in the Follow class. Next a user will *has many* 'followers' through the 'follower relationships' just created, while also using the 'follower' foreign_key created from 'user_id' in the Follow class. Again we have a similar snippet of code, except we are substituting the foreign key and source ('following'), since this is the followee of the relationship. Not too bad right?

I can't credit this all to my own, I read a few other blog posts that recited other programmers attempts and successes at creating following relationships (one of them being [here](https://medium.com/@esmerycornielle/making-a-followers-feature-with-ruby-on-rails-and-active-record-ddb3d1dda060), shout out to all you awesome people!) But what I will give back the web of wonders, is how I created my post methods for the actual act of following and unfollowing (oof!) someone. Creating and getting (unintentional pun there) these methods to work was a bit of a pain, but unlike me, you have this (hopefully helpful) blog post! Alright, let's get to it!

I created a followers_controller, and started with my follow method.
```ruby 

class FollowersController < ApplicationController

    post '/users/:id/follow' do
        follow_user = User.find_by_id(params[:id])

        if !current_user.following.include?(follow_user)
            current_user.following << follow_user
        end
        if !follow_user.followers.include?(current_user)
            follow_user.followers << current_user
        end
        redirect '/following'
       
    end

    get '/following' do
        erb :'/users/following'
    end

```
To create a follow, I made a post request to '/users/:id/follow', in this case the 'id' is the user_id of the person being followed, NOT the current user a.k.a you. This follow_user is the equivalent of the following made in the Follow class. This may get a bit confusing, so hang in there! In the next line of code:
```ruby
if !current_user.following.include?(follow_user)
```
I use following again, but through the *has many* and following relationships made in the User class. Here checks to see if the current user (you) has a following_relationship including the follow_user (the followee). If it doesn't, the follow_user (followee) will be appended into the following_relationships (similar to a fictional table of users and the people they follow, and vice versa).
```ruby
if !follow_user.followers.include?(current_user)
   follow_user.followers << current_user
end
```
In the next few lines of code, the same thing is happening except, now instead of adding a follow_user (followee) to a user, we are adding a user to follow_user (followee). The last few snippets demonstrate a get path I made that directs the user to a page of everyone they follow. And there you have it, we made a follow post request!

Making an unfollow request, believe it or not, is even easier!
Using the same route, but switching 'follow' to 'unfollow', we can do the request in three simple lines. Like before, I set the follow_user to the user_id (This is the user_id of the user being unfollowed). Then with one if statement, I checked to see the follow_user has myself, the 'current user' stored in their followers. If I, the current user, was stored in the followers, my next line of code destroys myself from the list of users inside followers. I then no longer follow that user! Pretty easy, right?
```ruby

    post '/users/:id/unfollow' do
        follow_user = User.find_by_id(params[:id])
        if follow_user.followers.include?(current_user)
            follow_user.followers.destroy(current_user)
        end
        redirect "/following"
    end
end

```
While I encourage reading more into following relationships and the actions that come along with them, this blog post should cover enough basics to implement follows in your own app. I hope you were able to follow along!