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

More than 1 year has passed since last update.

Ruby on Rails チュートリアル 14章 フォロー機能

Posted at

はじめに

Ruby on Railsチュートリアルの備忘録
チュートリアル学習者向けに書いています。
あとは備忘録
14章の内容です。この章は、モデル設計を理解するのが1番の重要で、これさえ理解できれば消化試合です。
チュートリアルと合わせてご覧ください。

migration生成

# referencesは使わない
# user_id:referenceだとuser_id modelを探しに行く挙動
rails generate model Relationship follower_id:integer followed_id:integer
class CreateRelationships < ActiveRecord::Migration[6.0]
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :followed_id

      t.timestamps
    end
    # 総フォロー数やフォロワー数はよく問い合わせるのでindex
    add_index :relationships, :follower_id
    add_index :relationships, :followed_id
    # 下記は一意生のために必要。 
    # フォローボタンを連打してもAがBをフォローは必ず1つになる
    add_index :relationships, [:follower_id, :followed_id], unique: true
  end
end

has_many

has_manyはメソットを作るためのメソットである
Userモデル

class User < ApplicationRecord

# UserのidとMicropostのuser_idを紐づける
has_many :microposts, dependent: :destroy
# Default: class_name : "Micropost"
# Default: foreign_key: "user_id"

# UserのidとRelationshipのfollower_idを紐づける
# active_relationshipsメソッドを作成(自身[が]フォローしてるrelationshipデータを全て取得)
has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
# Defaultではない設定
# class_name : Relationship
# foreign_key: follower_id

# @user.active_relationships.buildと
# すると自動的にfollower_idにuserを設定

belongs_to

Relationshipモデル

class Relationship < ApplicationRecord

# Relationshipのfollower_idとUserのidを紐づける
# followerメソッドを生成(そのデータのフォローしているuserを特定)
  belongs_to :follower, class_name: "User"
  # foren_key: follower_id
  # class: User
  # Relationship.first.followerが使える
  
  # DefaultだとclassはFollowerになってしまう
  
  belongs_to :followed, class_name: "User"
  # Relationship.first.followedが使える
end

バリデーションを追加

テストを書くならgenerateで自動生成されたfixtureを削除

app/models/relationship.rb

belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
validates :follower_id, presence: true
validates :followed_id, presence: true

has_many through

上記のhas_manyやbelong_toを実装したことで下記実装を行える

user.followingを作成(フォロー)

app/models/user.rb

class User < ApplicationRecord
.
.
# following メソッドを生成する(フォローしている人を全て特定する) @user.following

# Userインスタンスにactive_relationshipsメソッドを実行 (自身[が]フォローしているrelationshipデータを全て取得)
# 得られたdata1つ1つにfollowedメソッドを実行(誰をフォローしているのか特定)
has_many :following, through: :active_relationships, source: :followed
.
.
end

------------------------------------------------------------

# 関連づけをしたことによりフォローしているユーザーを配列のように扱うことができる
user.following.include?(other_user)
user.following.find(other_user)

# followingで取得したオブジェクトは、配列のように要素を追加したり削除したりすることができる。
user.following << other_user # 配列の最後に追記
user.following.delete(other_user)

user.followersを作成(フォロワー)

app/models/user.rb

class User < ApplicationRecord
.
.
# UserのidとRelationshipのfollowed_idを紐づける
# passive_relationshipsメソッドを作成(自分[を]フォロー全てのrelationshipデータを取得)
  has_many :passive_relationships, class_name:  "Relationship",
                                   foreign_key: "followed_id",
                                   dependent:   :destroy
                                   
  has_many :followers, through: :passive_relationships, source: :follower
.
.
end

便利メソッドを作成する

app/models/user.rb

# ユーザーをフォローする
  def follow(other_user)
    following << other_user
  end

  # ユーザーをフォロー解除する
  def unfollow(other_user)
    active_relationships.find_by(followed_id: other_user.id).destroy
  end

  # 現在のユーザーがフォローしてたらtrueを返す
  def following?(other_user)
    following.include?(other_user)
  end

これ以降はrails tutorial 14章を参照

2
0
1

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