There are many articles that describe the follow feature in Rails.
However, I felt that there were few articles explaining the implementation procedure up to "List page of users who ** follow me **" and "List page of users who ** follow me **". ..
This "follow list" and "follower list" can be confusing if you don't ** name the columns in the Relationship table carefully.
following
, follower
, follow
, followed
Various naming methods are mixed depending on the article, but since there were few articles that explained the naming method that is the least confusing, I decided to create an article again.
Let me start with the conclusion.
Keep in mind that in this article, ** followers should be `following
** and ** followers should be
`follower``` **.
The usual feeling is, "Isn't the follower
follower? You may feel. I won't explain it in detail because it will be long, but if you use that naming method, the column to be referred to when displaying the "follower list" of a user is not the `` `follower
column, but the other column. Since it becomes a column, various inconveniences occur.
It doesn't matter if you don't understand this meaning at this point, so here ** the followers are `following``` **, ** the followers are
`follower``` **. Please be aware that.
In the follow function, both the follower and the follower are users, so it is necessary to create a "many-to-many" relationship between the records in the User table.
To achieve this, we need to create an intermediate table that stores information about who to follow and who to follow.
For example, if User A follows User B, record the information as follows:
** User table **
id | name |
---|---|
1 | User A |
2 | User B |
** Relationship table **
id | following | follower |
---|---|---|
1 | 2 |
Type the following into the terminal to actually create the Relationship table, which is an intermediate table.
$ rails g model relationship following_id:integer follower_id:integer
$ rails db:migrate
Now you have an intermediate table called Relationship! The significance of the existence of this table is to save the following two pieces of information.
The information `following``` and
`follower``` in the Relationship model you just created must both be referenced from the parent User table. (Because both the follower and the follower are Users.)
By creating a following model and a follower model in a pseudo manner, the reference destination can be separated well.
Please change the Relationship model as follows.
app/models/relationship.rb
class Relationship < ApplicationRecord
belongs_to :following, class_name: "User"
belongs_to :follower, class_name: 'User'
end
By describing User in class_name, it is indicated that each reference destination is the User model.
Next, let's describe the association on the User model side.
First, add the following code together.
app/models/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
#Insert the following
has_many :following, class_name: "Relationship", foreign_key: "following_id", dependent: :destroy
has_many :follower, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy
has_many :following_user, through: :following, source: :follower
has_many :follower_user, through: :follower, source: :following
def follow(user_id)
following.create(follower_id: user_id)
end
def unfollow(user_id)
following.find_by(follower_id: user_id).destroy
end
def following?(user_id)
following_user.include?(user_id)
end
end
I will explain in order. First of all, about the following parts.
has_many :following, class_name: "Relationship", foreign_key: "following_id", dependent: :destroy
has_many :follower, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy
In the first has_many
, we are working on storing the user_id in the following_id of the Relationship model. At that time, foreign_key specifies the column that you want to explicitly store as `` `folowings_id```.
In the second has_many
, we are working on storing the user_id in the follower_id of the Relationship model. At that time, foreign_key specifies `` `follower_id``` and the column you want to explicitly store.
Next, about the following parts.
has_many :following_user, through: :following, source: :follower
has_many :follower_user, through: :follower, source: :following
Here, I'm just making an association using through to easily get the users I'm following and the users I'm following.
By doing this, you can get the information of the users you followed by writing, for example, @ user.following_user
.
Finally about this part
def follow(user_id)
following.create(follower_id: user_id)
end
def unfollow(user_id)
following.find_by(follower_id: user_id).destroy
end
def following?(user_id)
following_user.include?(user_id)
end
end
Here, we have created a function to follow, a function to unfollow, and a function to check if the user is already following.
This completes the description of the most difficult association with the follow function! Once you get here, it's easy if you understand the basic MVC!
In preparation for defining actions to follow and unfollow, let's first route as follows.
config/routes.rb
post 'follow/:id' => 'relationships#follow', as: 'follow'
delete 'unfollow/:id' => 'relationships#unfollow', as: 'unfollow'
Next, in order to create the "Follow List" and "Follower List" pages, perform the following routing as well.
config/routes.rb
resources :users, only: [:show] do
#Insert the following
get :following, :follower, on: :member
end
Next is the definition of the action in the relationships controller.
First, let's create a relationships controller by typing the following code in the terminal.
$ rails g controller Relationships new
Define a follow action that allows you to follow a user and an unfollow action that allows you to unfollow a user as follows:
app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
def follow
current_user.follow(params[:id])
redirect_back(fallback_location: root_path)
end
def unfollow
current_user.unfollow(params[:id])
redirect_back(fallback_location: root_path)
end
end
Next, describe the actions required to display the "follow list" and "follower list" on the users controller as follows.
app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
#Insert the following
def following
@user = User.find(params[:id])
end
def follower
@user = User.find(params[:id])
end
end
All you have to do is write it in the view! !!
Here is an example of writing a follow button and an unfollow button on the user # show page.
This is just an example, so please rewrite it as appropriate to suit your product.
html:app/views/users/show.html.erb
<% if user_signed_in? %>
<% unless @user == current_user %>
<% if current_user.following?(@user) %>
<%= link_to unfollow_path(@user.id), method: :delete, :style=>"color:#E0245E;" do %>
<i class="fas fa-heart"></i>
<% end %>
<% else %>
<%= link_to follow_path(@user.id), method: :post do %>
<i class="far fa-heart"></i>
<% end %>
<% end %>
<% end %>
<% end %>
Below is an example of a link code to jump to the "Follow List" and "Follower List".
html:app/views/users/show.html.erb
<a href="<%= following_user_path(@user) %>">
<%= @user.following.count %> following
</a>
<a href="<%= follower_user_path(@user) %>">
<%= @user.follower.count %> followers
</a>
Also, in the "Follow list" and "Follower list", refer to the following and describe the information you want to display as appropriate.
html:app/views/users/following.html.erb
<% @user.following_user.each do |user| %>
<% user.name %>
<% end %>
html:app/views/users/follower.html.erb
<% @user.follower_user.each do |user| %>
<% user.name %>
<% end %>
This is completed! Thank you for your hard work!
Recommended Posts