0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】フォロー機能について

Posted at

記事概要

Ruby on Railsにフォロー機能を実装する方法について、まとめる

前提

  • Ruby on Railsでアプリケーションを作成している

サンプルアプリ(GitHub)

フォロー機能

仕組み

フォローする側とフォローされる側のUserは多対多の関係になる

Image from Gyazo

ER図

Userモデルは1つしか存在しないので、フォローする側とされる側のUserを区別できない

class_nameというオプションを使用することで、1つのモデルを便宜的に異なる2つのモデルとして考えられる。FollowingモデルとFollowerモデルの2つのモデルがあると仮定してER図を書く

Image from Gyazo

手順1(必要なモデルを作成)

  1. Relationshipモデルを作成する
    % rails g model relationship
    
  2. 必要なカラムを追加するため、マイグレーションファイルを編集する
    db/migrate/20XXXXXXX_create_relationships.rb
    class CreateRelationships < ActiveRecord::Migration[7.1]
      def change
        create_table :relationships do |t|
          t.references :following
          t.references :follower
          t.timestamps
        end
      end
    end
    
  3. 下記コマンドを実行する
    % rails db:migrate
    

手順2(アソシエーションを設定)

  1. Relationshipモデルを編集する
    app/model/relationship.rb
    class Relationship < ApplicationRecord
      belongs_to :following, class_name: "User" # Userモデルに対して、2つのアソシエーションを組む
      belongs_to :follower, class_name: "User" # Userモデルに対して、2つのアソシエーションを組む
    end
    
  2. Userモデルを編集する
    app/model/user.rb
      # 省略
      
      # フォローする側のUserから見た中間テーブルを「active_relationship」と再定義し、外部キー制約を設定
      has_many :active_relationships, class_name: "Relationship", foreign_key: :following_id
      # throughオプションで中間テーブル(active_relationships)と紐付け、sourceオプションで参照先モデル(follower)を指定
      has_many :followings, through: :active_relationships, source: :follower
    
      # フォローされる側のUserから見た中間テーブルを「passive_relationship」と再定義し、外部キー制約を設定
      has_many :passive_relationships, class_name: "Relationship", foreign_key: :follower_id
      # throughオプションで中間テーブル(passive_relationships)と紐付け、sourceオプションで参照先モデル(following)を指定
      has_many :followers, through: :passive_relationships, source: :following
    end
    

手順3(ルーティングを設定)

  1. ルーティングを設定する
    config/routes.rb
      # 省略
      
      # usersとrelationshipsをネストする
      resources :users do
        resource :relationships, only: [:create, :destroy]
      end
    end
    

手順4(ビューを作成)

フォローの有無によって動的に表示を変える

  1. フォローしているかどうか判定するメソッドを作成する
    app/model/user.rb
      # 省略
      
      # フォローしているかどうか判定するメソッド
      def followed_by?(user)
        # 中間テーブルを参照して、ユーザーidと一致するfollowing_idが存在すればその情報を取得。存在しなければnilを返す
        follower =  passive_relationships.find_by(following_id: user.id)
        # followerに値が存在していればtrueを返し、存在していなければfalseを返す
        return follower.present?
      end
    end
    
  2. フォローボタンを作成するため、app/views/users/show.html.erbを編集する
    <div class="user-paged">
      <div class="user-contentsd">
        <p class="user-named">ユーザー名:<%= @user.name %></p>
    
        <%#= フォローボタン %>
        <% if @user.followed_by?(current_user) %>
          <%=link_to "フォロー中", user_relationships_path(@user.id),class: "btn", data: { turbo_method: :delete } %>
        <% else %>
          <%=link_to "フォローする", user_relationships_path(@user.id),class: "btn", data: { turbo_method: :post } %>
        <% end %>
        
      </div>
    </div>
    

手順5(コントローラーを作成)

  1. Relationshipコントローラーを作成する
    % rails g controller relationships
    
  2. createアクションを定義する
    app/controllers/relationships_controller.rb
    class RelationshipsController < ApplicationController
      def create
        # ログイン中のユーザーに紐づいている中間テーブルの値を全て取得し、インスタンスを生成
        follow = current_user.active_relationships.new(follower_id: params[:user_id])
        # フォローした記録をDBに保存
        follow.save
        # TOPページに移動
        redirect_to root_path
      end
    end
    
    • current_user.active_relationshipsと記述することで、ログイン中のユーザーに紐づいている中間テーブルの値を全て取得できる
    • newメソッドで、current_user.active_relationshipsのインスタンスを生成する
    • (follower_id: params[:user_id])の記述によって、生成する中間テーブルの値を指定する
      • 具体的には、中間テーブルのカラムであるfollower_idparamsに格納されているuser_idが一致するインスタンスを生成する
  3. destroyアクションを定義する
    app/controllers/relationships_controller.rb
      # 省略
      
      def destroy
        # ログイン中のユーザーと紐づいている中間テーブルの値を全て取得し、find_byメソッドを使用して該当する情報をDBから取得
        follow = current_user.active_relationships.find_by(follower_id: params[:user_id])
        # DBからフォローした記録を削除
        follow.destroy
        # TOPページに移動
        redirect_to root_path
      end
    end
    

手順6(ブラウザで動作確認)

  1. サーバーを起動する
  2. フォローできることを確認する
    Image from Gyazo
  3. 値がDBに保存されていることを確認する
    Image from Gyazo
  4. フォロー解除できることを確認する
    Image from Gyazo
  5. 値がDBに保存(データ削除)されていることを確認する
    Image from Gyazo

手順7(コントローラーを編集)

現状の実装では、自分自身に対してフォローすることが可能
Image from Gyazo

  1. 自分自身をフォローできないようにするため、app/views/users/show.html.erbを編集する
    <div class="user-paged">
      <div class="user-contentsd">
        <p class="user-named">ユーザー名:<%= @user.name %></p>
    
        <%#= ログインユーザーと一致しない場合のみ、フォローボタンを表示 %>
        <% if current_user != @user %>
          <% if @user.followed_by?(current_user) %>
            <%=link_to "フォロー中", user_relationships_path(@user.id),class: "btn", data: { turbo_method: :delete } %>
          <% else %>
            <%=link_to "フォローする", user_relationships_path(@user.id),class: "btn", data: { turbo_method: :post } %>
          <% end %>
        <% end %>
    
      </div>
    </div>
    
  2. 自身のユーザー画面だとフォローボタンが表示されないことを、ブラウザで確認する
    Image from Gyazo

手順8(「フォロー中のユーザー」と「フォロワー」を表示)

  1. フォロワーを表示するため、app/views/users/show.html.erbを編集する
        <%#= 省略 %>
        
        <%#= フォロワーを表示 %>
        <h3>フォロワー</h3>
        <% @user.followers.each do |user| %>
          <p class=“f-user”><%= link_to user.name, user_path(user.id) %></p>
        <% end %>
      </div>
    </div>
    
    • @user.followersは、@userに格納されているユーザーのフォロワー情報を全て取得する
  2. フォロワーが表示されることを、ブラウザで確認する
    Image from Gyazo
  3. フォローしているユーザーを表示するため、app/views/users/show.html.erbを編集する
        <%#= 省略 %>
        
        <%#= フォローを表示 %>
        <h3>フォロー</h3>
        <% @user.followings.each do |user| %>
          <p class=“f-user”><%= link_to user.name, user_path(user.id) %></p>
        <% end %>
    
        <%#= フォロワーを表示 %>
        <h3>フォロワー</h3>
        <% @user.followers.each do |user| %>
          <p class=“f-user”><%= link_to user.name, user_path(user.id) %></p>
        <% end %>
      </div>
    </div>
    
    • @user.followingsは、@userに格納されているユーザーのフォロー情報を全て取得する
  4. フォローが表示されることを、ブラウザで確認する
    Image from Gyazo
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?