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.
Rails 5.2.3
Ruby 2.6.0
The goal this time is like this. When you press the button, the follow / unfollow button will appear asynchronously with the crispness.
The usage of this function is as follows.
--Users can follow other users --You cannot follow the same user twice --Users cannot follow themselves
To find out why this happens, read Last article: relaxed:
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.
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.
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.
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
**. Js.erb
fileThe 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) %>")
It's done here ^^ All you have to do to make Ajax is rewrite the view file: relaxed: Simple: sparkles:
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