How to Treat Your Followers
Tags: followerstable, rails, react
Published: 2023-01-23 04:53:14

Hello loyal blog readers,

How are you both doing? So today's blog is going to focus on how I'm dealing with "followers" for the social media app that I'm creating. Before I started on the app, I already understood that followers are created by making a join table between two users - "the follower" and the "user_they_follow". There were a variety of articles I was able to find on the internet that walked me through how to create that relationship in my Follow model - _this one serves as a good example_ (https://betterprogramming.pub/how-to-create-a-follow-feature-in-rails-by-aliasing-associations-30d63edee284) - but I'm going to focus on some ways you can treat your followers after you've created that basic relationship.

Since most people on social media are obsessed with seeing how many followers they have at any given time, I knew I could just leave this important information sitting in the backend. I needed to get those details displayed on the page so that the mythical people that are using my can brag to each other about their followers. So, I needed to create some methods. Method #1 was pretty straightforward - I wanted to display how many followers each user has on their homepage.

For this I just needed to create a simple method in the User model:

    def total_followers
        self.followers.length
    end

Here I'm just taking current user and accessing all of the followers they have through the has_many relationship and then grabbing the total number of those followers using .length. I then add total_followers to the user_serializer attributes, and display user.total_followers on the front and I have a super straightforward way to satisfy the narcissists on the app.

I created an equally simple approach to total up the number of people a user is following with method #2:

    def total_users_you_follow
        self.users_they_follow.length
    end

Now, it's not enough for people to just know _how many_ people are following them - they also want to know _who_ is following them. So, for this I went back to my user model and created method #3:     

    def list_followers
        self.followers.map do |follower|
            follower.username
        end
    end

In this instance, I'm taking the current user and I map through all of the followers and return an array of all of the usernames of those followers. Now, later on, I might want to pass on more than the names and perhaps set up a new serializer so that I can actually send along more follower data to display, but since this project has to be turned in in two days, I'm just gonna handle the names for now. I posted the names as a string by posting the following to the page user.list_followers.toString().

Again, I just had to slightly alter things to gather the same info for who the users are following and method #4:

    def list_users_you_follow
        self.users_they_follow.map do |followed|
            followed.username
        end
    end

OK, that was all working, but I still had one more issue I wanted to resolve.  Each user page has a "Follow me" button that when clicked sends the info to the backend and enters the user_id for both the follower and who they're following in the follows table, but, at the moment there is no indication on the front end that anything has happened. So I want to set up a ternary to display "Follow me" if the current user doesn't follow the person whose page they're viewing and "You Follow" if they do not follow that person. So... how do I implement this? 

My first thought was another method since I was on a roll with those, but then I realized I could further utilize a couple of the methods I'd just written.

In the UserPage.js component, I declared a new boolean variable:

    let alreadyFollow = false

In the component, I already have a variable called userPageInfo that contains all of the into for the user whose page it is. So I can use the list_followers method to grab all of the followers for that user and then search through them:

     userPageInfo.list_followers.forEach((fol) => {

I could then just compare each follower username to the username of who is currently logged in

            if (fol === user.username) 

and then if I find a match I simply change the already follow variable to true. Seems easy enough. Let's check to see if it works.

            TypeError: Cannot read properties of undefined 
            (reading 'forEach')

Come on!! Why didn't that work? Oh... I just realized that the Userpage that I'm currently on is a user without any followers yet, so the forEach is trying to map through nothing and hitting the error. I can fix this!... I hope.

I just have to wrap the forEach loop in another if statement and I will once again call on one of the methods I've already written.

     if (userPageInfo.total_followers > 0)

So now, the forEach will only run if the User has followers and if not, the alreadyFollow boolean will stay false as desired. Let's check it out... 

Success!! So here's final version of the if statement, forEach loop.

    if (userPageInfo.total_followers > 0) {
        userPageInfo.list_followers.forEach((fol) => {
            if (fol === user.username) {
                alreadyFollow = true
                console.log(alreadyFollow)
            }
        })
    }

And here is the ternary I use to put the correct follow button on the page:

    <h5>
      {alreadyFollow ? <button> You Follow 
      {userPageInfo.username} </button>
      : <button onClick={handleFollow}>Follow 
      {userPageInfo.username}</button>}
    </h5>

Perfect. So now everybody knows who's following who and I'll leave it to them to figure out why.