0
2

More than 3 years have passed since last update.

フォロー機能がほしいぃぃ ❏Rails❏

Last updated at Posted at 2019-12-01

RailsTutorialを参考にフォロー機能をつけました。

簡単にまとめます。

※クラス名・id名は本家と変えたところがあります。
※ところどころ自己流にアレンジしています。ご容赦ください。

Relationshipモデル

ターミナル
$ rails g model Relationship follower_id:integer followed_id:integer
db/migrate/20191128014554_create_relationships.rb
class CreateRelationships < ActiveRecord::Migration[5.2]
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :followed_id

      t.timestamps
    end
    add_index :relationships, :follower_id
    add_index :relationships, :followed_id
    add_index :relationships, [:follower_id, :followed_id], unique: true
  end
end
ターミナル
$ rails db:migrate
app/models/relationship.rb
class Relationship < ApplicationRecord
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"
  validates :follower_id, presence: true
  validates :followed_id, presence: true
end

Userモデル

app/models/user.rb
class User < ApplicationRecord
  
  has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy
  has_many :passive_relationships, class_name: "Relationship", foreign_key: "followed_id", dependent: :destroy
  has_many :following, through: :active_relationships, source: :followed
  has_many :followers, through: :passive_relationships, source: :follower

  def follow(other_user)
    following << other_user
  end

  def unfollow(other_user)
    active_relationships.find_by(followed_id: other_user.id).destroy
  end

  def following?(other_user)
    following.include?(other_user)
  end
end

ルーティング

app/config/locals/routes.rb
Rails.application.routes.draw do
  
  resources :users, only: [:show] do
    member do
      get :following, :followers
    end
  end
  resources :relationships, only: [:create, :destroy]
end

ビュー

app/views/users/_stats.html.haml
- @user ||= current_user
%div
  = link_to following_user_path(@user) do
    #following
      = @user.following.count
  = link_to followers_user_path(@user) do
    #followers
      = @user.followers.count
app/views/users/_follow_form.html.haml
- unless current_user == @user
  #follow_form
    - if current_user.following?(@user)
      = render 'unfollow'
    - else
      = render 'follow'
app/views/users/_follow.html.haml
= form_for(current_user.active_relationships.build, remote: true) do |f|
  = hidden_field_tag :followed_id, @user.id
  = f.submit "Follow", class: "btn btn-primary"
app/views/users/_unfollow.html.haml
= form_for(current_user.active_relationships.find_by(followed_id: @user.id), html: { method: :delete }, remote: true) do |f| 
  = f.submit "Unfollow", class: "btn"
xxx.html.haml
#好きなところへ
= render "stats"
= render "follow_form" if user_signed_in?



以下2つは完全自己流なのでスルーしてください。

following.html.haml
.contents
  = render "tweets/side-bar"
  .contents__right
    .contents__right__tweets
      .contents__right__tweets__follows
        .contents__right__tweets__follows__user-nickname
          = @user.nickname
          さん
        .contents__right__tweets__follows__text
          フォロー中
      - @users.each do |user|
        .contents__right__tweets__follow-users
          %p.contents__right__tweets__follow-users__user
            = link_to "#{user.nickname}", user_path(user)
      .contents__right__tweets__paginate
        = paginate(@users)
followers.html.haml
.contents
  = render "tweets/side-bar"
  .contents__right
    .contents__right__tweets
      .contents__right__tweets__follows
        .contents__right__tweets__follows__user-nickname
          = @user.nickname
          さん
        .contents__right__tweets__follows__text
          フォロワー
      - @users.each do |user|
        .contents__right__tweets__follow-users
          %p.contents__right__tweets__follow-users__user
            = link_to "#{user.nickname}", user_path(user)
      .contents__right__tweets__paginate
        = paginate(@users)

本家はshow_follow.html.erbというビューファイルを作って、そこにレンダリングしています。
僕はfollowing followers2つのビューファイルを作りました。冗長かもしれませんが明確に分けて管理したかったのでこうしました。

コントローラー

relationships_controller.rb
class RelationshipsController < ApplicationController
  before_action :authenticate_user!

  def create
    @user = User.find(params[:followed_id])
    current_user.follow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end
end
users_controller.rb
class UsersController < ApplicationController
  before_action :authenticate_user!, only: [:following, :followers]

  

  def following
    @user = User.find(params[:id])
    @users = @user.following.page(params[:page]).per(3)
  end

  def followers
    @user = User.find(params[:id])
    @users = @user.followers.page(params[:page]).per(3)
  end
end



本家大正義RailsTutorial

https://railstutorial.jp/chapters/following_users?version=5.1#cha-following_users



ではまた!

0
2
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
2