Implement user follow function in Rails (I use Ajax) ②

What did you do

This article is a continuation of this article.

▼ Previous article Implement user follow function in Rails (I use Ajax) ①

Carrying out Rails challenges. We have decided to implement the follow function of User. In the previous articles, we have created the migration file and defined the association to the model file, so this time we will add controller, view, and ** model method **.

The execution environment is as follows.

goal

The goal this time is like this. When you press the button, the follow / unfollow button will appear asynchronously with the crispness.

Image from Gyazo

specification

The usage of this function is as follows.

--Users can follow other users --You cannot follow the same user twice --Users cannot follow themselves

data structure

The DB design is as follows. Image from Gyazo

To find out why this happens, read Last article: relaxed:

Non-asynchronous implementation

First, we will implement it in a non-asynchronous manner. I will write both controller and model lightly, so if you want to know more, you may want to read the article around here.

-Create a "Like" function with Rails-② Create action for "Like" -Create a "Like" function in Rails-③ Enable to cancel "Like" -Implement the "Like" function in Ajax in Rails.

controller

The description of controller is as follows.

relationships_controller.rb


class RelationshipsController < ApplicationController
  def create
    @other_user = User.find(params[:follower])
    current_user.follow(@other_user)
  end

  def destroy
    @user = current_user.relationships.find(params[:id]).follower
    current_user.unfollow(params[:id])
  end
end

follow and unfollow are model methods. I will explain later.

view The description of the view file is as follows. The class for decoration is omitted. It is assumed that the variable representing user (each user) is passed from outside the code displayed here.

view


- if logged_in? && current_user != user
  - if current_user.following?(user)
    = button_to 'Unfollow', relationship_path(current_user.relationships.find_by(follower: user)), method: :delete
  - else
    = button_to 'Follow', relationships_path(follower: user)

following? Is also a model method.

model

Define follow, unfollow, and following? Methods as model methods for the user model, respectively.

python


class User < ApplicationRecord
  #The part defined in the previous article
  has_many :relationships, dependent: :destroy
  has_many :followings, through: :relationships, source: :follower

  has_many :passive_relationships, class_name: 'Relationship', foreign_key: 'follower_id', dependent: :destroy
  has_many :followers, through: :passive_relationships, source: :user

  #Model method added this time
  def follow(other_user)
    return if self == other_user

    relationships.find_or_create_by!(follower: other_user)
  end

  def following?(user)
    followings.include?(user)
  end

  def unfollow(relathinoship_id)
    relationships.find(relathinoship_id).destroy!
  end
end

Above this class is Complex Associations as appropriate in the previous article.

Implementation completed with non-asynchronous communication

At this point, the non-Ajax follow function is complete. Since the screen is transitioned with redirect_to for the demo, it looks a bit asynchronous, but after pressing the" Follow "button and reloading the screen, the" Unfollow "button appears.

Image from Gyazo

Implementation in Ajax

Now let's make this an asynchronous communication. This is also written lightly, so if you are wondering why this happens, please see this article.

remote: true to POST ajax posts.

html part

First, cut out the button part partially with the remote: true option.

ruby:views/relationships/_follow_button.html.slim


= button_to 'Follow', relationships_path(follower: user), remote: true

ruby:views/relationships/_unfollow_button.html.slim


= button_to 'Unfollow', relationship_path(current_user.relationships.find_by(follower: user)), method: :delete, remote: true
#View file that originally had a button
- if logged_in? && current_user != user
 div id="follow-button-#{user.id}"
   - if current_user.following?(user)
      = render 'relationships/unfollow_button', user: user
   - else
      = render 'relationships/follow_button', user: user

Create a **. Js.erb file

The file of the part to be called dynamically is written to the **. Js.erb file.

erb:views/relationships/create.js.erb


$("#follow-button-<%= @other_user.id %>").html("<%= j(render 'unfollow_button', user: @other_user) %>")

erb:views/relationships/destroy.js.erb


$("#follow-button-<%= @user.id %>").html("<%= j(render 'follow_button', user: @user) %>")

Complete!

It's done here ^^ All you have to do to make Ajax is rewrite the view file: relaxed: Simple: sparkles:

Image from Gyazo

Impressions etc.

The follow / unfollow function has a data structure of 80%! The design of the DB and model is complicated, isn't it? I'm glad I read it well ^^

Recommended Posts

Implement user follow function in Rails (I use Ajax) ②
Implement user follow function in Rails (I use Ajax) ①
Implement follow function in Rails
Implemented follow function in Rails (Ajax communication)
I tried to implement Ajax processing of like function in Rails
Implement application function in Rails
[Rails] Implement User search function
Implement simple login function in Rails
Implement CSV download function in Rails
Implement user registration function and corporate registration function separately in Rails devise
Rails follow function
[Rails 6] Asynchronous (Ajax) follow function is implemented
Use [Rails] devise Guest user function (for portfolio)
Implement star rating function using Raty in Rails6
Implement the Like feature in Ajax with Rails.
How to make a follow function in Rails
Follow function (Ajax) implementation
[Rails] Implement search function
Use images in Rails
Implement markdown in Rails
[Rails / JavaScript / Ajax] I tried to create a like function in two ways.
Implement post search function in Rails application (where method)
How to implement a like feature in Ajax in Rails
Introduce devise in Rails to implement user management functionality
I want to use a little icon in Rails
I want to define a function in Rails Console
Implement LTI authentication in Rails
[Rails] (Supplement) Implemented follow function
Implement import process in Rails
Ajax bookmark function using Rails
Use multiple checkboxes in Rails6!
[Rails] Implement image posting function
Implement login function in Rails simply by name and password (1)
Implement login function in Rails simply by name and password (2)
Implement login function simply with name and password in Rails (3)
[Rails] I tried to implement "Like function" using rails and js
Use voice recognition function in Unity
[Rails] A simple way to implement a self-introduction function in your profile
Add a search function in Rails.
I tried to implement the image preview function with Rails / jQuery
[Rails] Use cookies in API mode
Implement tagging function in form object
Implement PHP implode function in Java
Implement a contact form in Rails
Implement star evaluation function in Rails 6 (Webpacker is installed as standard)
[Rails] I will explain the implementation procedure of the follow function using form_with.
[Rails] Use devise to get information about the currently logged in user
"Teacher, I want to implement a login function in Spring" ① Hello World
[Rails] Function restrictions in devise (login / logout)
How to use custom helpers in rails
[Ruby on Rails] Follow function implementation: Bidirectional
How to use MySQL in Rails tutorial
How to implement ranking functionality in Rails
I want to use @Autowired in Servlet
How to use credentials.yml.enc introduced in Rails 5.2
Implement button transitions using link_to in Rails
How to implement image posting function using Active Storage in Ruby on Rails
Where I got stuck in today's "rails tutorial" (2020/10/08)
Create authentication function in Rails application using devise
[Rails] When I use form_with, the screen freezes! ??
I tried to implement polymorphic related in Nogizaka.