#目標
開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina
前提
下記実装済み。
・Slim導入
・Bootstrap3導入
・ログイン機能実装
フォロー機能を実装
1.モデル
$ rails g model Relationship follower_id:integer followed_id:integer
$ rails db:migrate
ActiveRecord::Schema.define(version: 2020_04_05_115005) do
create_table "relationships", force: :cascade do |t|
t.integer "follower_id"
t.integer "followed_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,:validatable
has_many :books, dependent: :destroy
has_many :follower, class_name: 'Relationship', foreign_key: 'follower_id', dependent: :destroy
has_many :followed, class_name: 'Relationship', foreign_key: 'followed_id', dependent: :destroy
has_many :following_user, through: :follower, source: :followed
has_many :follower_user, through: :followed, source: :follower
# ユーザーをフォローする
def follow(user_id)
follower.create(followed_id: user_id)
end
# ユーザーをアンフォローする
def unfollow(user_id)
follower.find_by(followed_id: user_id).destroy
end
# フォローしているかを確認する
def following?(user)
following_user.include?(user)
end
end
① has_many :follower, class_name: 'Relationship', foreign_key: 'follower_id', dependent: :destroy
➡︎ Relationshipモデルのfollower_idにuser_idを格納
②has_many :followed, class_name: 'Relationship', foreign_key: 'followed_id', dependent: :destroy
➡︎ Relationshipモデルのfollower_idにuser_idを格納
③ has_many :following_user, through: :follower, source: :followed
➡︎ 自分がフォローしているユーザー
④ has_many :follower_user, through: :followed, source: :follower
➡︎ 自分をフォローしているユーザー
class Relationship < ApplicationRecord
belongs_to :follower, class_name: 'User'
belongs_to :followed, class_name: 'User'
end
2.コントローラー
$ rails g controller relationships
class RelationshipsController < ApplicationController
# フォローする
def follow
current_user.follow(params[:id])
redirect_to users_path
end
# アンフォローする
def unfollow
current_user.unfollow(params[:id])
redirect_to users_path
end
end
class UsersController < ApplicationController
def index
@users = User.all
end
# 自分がフォローしているユーザー一覧
def following
@user = User.find(params[:user_id])
@followings = @user.following_user.where.not(id: current_user.id)
end
# 自分をフォローしているユーザー一覧
def follower
@user = User.find(params[:user_id])
@followers = @user.follower_user.where.not(id: current_user.id)
end
end
3.ルーティング
Rails.application.routes.draw do
post 'follow/:id', to: 'relationships#follow', as: 'follow'
post 'unfollow/:id', to: 'relationships#unfollow', as: 'unfollow'
get 'users/following/:user_id', to: 'users#following', as:'users_following'
get 'users/follower/:user_id', to: 'users#follower', as:'users_follower'
end
4.ビュー
.row
.col-xs-2
.col-xs-8
table.table
thead
tr
th
| 氏名
th
| 自己紹介
th
th
th
tbody
- @users.each do |user|
tr
td
= link_to user do
= user.name
td
= user.introduction
td
/ 自分がフォローしているユーザー一覧
= link_to "#{ user.follower.count }フォロー中", users_following_path(user)
td
/ 自分をフォローしているユーザー一覧
= link_to "#{ user.followed.count }フォロワー", users_follower_path(user)
td
- unless user == current_user
- if current_user.following?(user)
= link_to 'フォロー解除', unfollow_path(user), method: :post, class: 'btn btn-info'
- else
= link_to 'フォローする', follow_path(user), method: :post, class: 'btn btn-default'
.col-xs-2
非同期機能を実装
1.jQueryを導入
gem 'jquery-rails'
$ bundle
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require jquery
//= require_tree .
2.ビューを編集
/ 各フォロー中一覧のリンクにIDを付与
td id='following-count_#{ user.id }'
= link_to "#{ user.follower.count }フォロー中", users_following_path(user)
/ 各フォロワー一覧のリンクにIDを付与
td id='follower-count_#{ user.id }'
= link_to "#{ user.followed.count }フォロワー", users_follower_path(user)
td
- unless user == current_user
/ 各フォローボタンにIDを付与
span id='follow-button_#{ user.id }'
/ フォローボタンをパーシャル化
= render 'users/follow-button', user: user
/ フォローボタンに「remote: true」を付与
- if current_user.following?(user)
= link_to 'フォロー解除', unfollow_path(user), method: :post, class: 'btn btn-info', remote: true
- else
= link_to 'フォローする', follow_path(user), method: :post, class: 'btn btn-default', remote: true
「remote: true」
を付与する事で、JavaScriptファイルを呼び出せる様になる。
2.JavaScriptファイルを作成
$("#follow-button_<%= @user.id %>").html("<%= j(render 'users/follow-button', user: @user) %>");
$("#follower-count_<%= @user.id %>").html('<%= link_to "#{ @user.followed.count }フォロワー", users_follower_path(@user) %>');
$("#following-count_<%= current_user.id %>").html('<%= link_to "#{ current_user.follower.count }フォロー中", users_following_path(@user) %>');
$("#follow-button_<%= @user.id %>").html("<%= j(render 'users/follow-button', user: @user) %>");
$("#follower-count_<%= @user.id %>").html('<%= link_to "#{ @user.followed.count }フォロワー", users_follower_path(@user) %>');
$("#following-count_<%= current_user.id %>").html('<%= link_to "#{ current_user.follower.count }フォロー中", users_following_path(@user) %>');
$("#follow-button_<%= @user.id %>").html("<%= j(render 'users/follow-button', user: @user) %>");
➡︎ フォローボタンを非同期で処理
$("#follower-count_<%= @user.id %>").html('<%= link_to "#{ @user.followed.count }フォロワー", users_follower_path(@user) %>');
➡︎ フォロワーカウント数を非同期で処理
$("#following-count_<%= current_user.id %>").html('<%= link_to "#{ current_user.follower.count }フォロー中", users_following_path(@user) %>');
➡︎ フォロワー中カウント数を非同期で処理