LoginSignup
1

More than 1 year has passed since last update.

posted at

【フォロー機能】ruby/rails (フォローする側のモデルのつながりのみ解説)

【フォロー機能】ruby/rails

私はフォロー機能をつけるときにとても苦労しました。
なので自分用のメモとしても含めて解説を残したいと思います。
(すでに同類のとてもきれいなqiitaの記事が複数ありますが・・・)

railsチュートリアルに書かれているフォロー機能の付け方が私にとって一番わかりやすいと思ったのでチュートリアルの書き方をベースに解説していきたいと思います。

この記事ではフォロー機能の付け方全部を説明するのではなくポイントになるところを抑えたいと思います。

【前提】

userモデルの1つのidの人が別のidの人をフォローすることにする。
例えばid(1)の人がid(2)の人をフォローするということ。
(単にユーザーがユーザーをフォローするということを伝えたいだけです。)


以下の図はファイルとして作らなければいけないモデルの数が2つあることを表しています。
この時点ではrelationshipsモデルがなんとな~く中間モデルとしてあるっぽいと思っていただければ十分です。

リレーション.png

次に各モデルの中身を記述していきます。

models/user.rb

  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

models/relationship.rb

  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"

上の二つのモデルの中に記述したリレーション図はこんな感じです。
(フォローする側のみで書いています)

全体.png

モデル2つだけじゃないの??と思った方
userとfollower(user)とfollowing(followed)は元はuserモデル1つです。
これは実はuserモデルを中で種類別に分けています。
下の部分はフォローされる側のリレーションの関係のため今回は解説を割愛します。
(フォローする側とほぼまったく同じ原理です)

models/user.rb

  has_many :passive_relationships, class_name: "Relationship",
                                   foreign_key: "followed_id",
                                   dependent: :destroy
  has_many :followers, through: :passive_relationships, source: :follower

models/relationship.rb

  belongs_to :followed, class_name: "User"

リレーションの関係を理解することが最関門、最重要です。
まずは書いてあることの意味を一つずつ理解していきましょう。

解説⑴

models/user.rb

  has_many :active_relationships,  class_name: "Relationship",
                                   foreign_key: "follower_id",
                                   dependent: :destroy

①has_many :active_relationships
userモデルがactive_relationshipsとhas_manyのリレーションをかけている。

②class_name: "Relationship"
Relationshipモデルの名前を変えてactive_relationshipsという名前にする。

③foreign_key: "follower_id"
active_relationshipsは外部キーを持っておりそれは"follower_id"(フォローされた人のid)である。

これら3つをつなげると
userモデルからactive_relationships(relationship)モデルにhas_manyのリレーションをかけている。
更にrelationshipモデルはフォローされた人のidを外部キーとして持っている。

次に行きます。

解説⑵

models/user.rb

  has_many :following, through: :active_relationships, source: :followed

①has_many :following,
userがfollowingモデルに対してリレーションをかけている

②through: :active_relationships,
リレーションをかけるときactive_relationshipsが中間モデルとなりパイプ役になっている。

③source: :followed
関連付けのもとの名前を指しています。
userモデルのfollowedを使っているよということ。
これは解説⑶の説明も必要になります。

これら3つをつなげると
userモデルがfollowing(followed)というモデルにリレーションをかけている。
そしてその間にactive_relationshipsが中間モデルとしてある。

次に行きます。

解説⑶

models/relationship.rb

  belongs_to :follower, class_name: "User"

①belongs_to :follower, class_name: "User"
relationshipモデルはfollowerモデルにbelongs_toのリレーションをかけている
followerモデルはuserモデルの名前を変えているものである。

3つをつなげる

⑴⑵⑶を持ってきます。
~~~~~~~~~~~~~~~~~~~~~~~

userモデルからactive_relationships(relationship)モデルにhas_manyのリレーションをかけている。
更にrelationshipモデルはフォローされた人のidを外部キーとして持っている。


userモデルがfollowing(followed)というモデルにリレーションをかけている。
そしてその間にactive_relationshipsが中間モデルとしてある。


active_relationship(relationship)モデルはbelongs_toでfollowerモデルにリレーションをかけている。
followerモデルはuserモデルの名前を変えているものである。
~~~~~~~~~~~~~~~~~~~~~~~

これらの3つの文章をつなげようと思います。
説明しやすいように順番が少し変わります。

^^^^^^^^^^^^^^^^^^^^^^^
①ユーザーがfollowingモデルと繋がり、その間には中間モデルがある。⑵の部分
②中間モデルはフォローされた人のID(follower_id)を持つ。⑴の部分
③フォローされた人のIDである、follower_id(followers)のモデルはuserモデルの名前を変えただけ。
また、①のfollowingモデルもuserモデルの名前を変えただけ。
userモデルの名前を種類別に変え、それら同士で中間テーブルを挟んでお互いをリレーションかけられるようにする。⑶の部分
^^^^^^^^^^^^^^^^^^^^^^^^
変えただけというのは最初のほうに話したモデルの中で種類別にしているという意味になります。
フォローされた人というのはactive_relationshipにおいてフォローした人からしてフォローされたのは誰か見極めているものです。
フォローされた人から誰がフォローしたのかは割愛した要素が補います。

もっと短くまとめると

userモデルを2種類に分け、中間テーブルを挟みリレーションをかさせあわす。
の一言だと思います。

以上です。

アドベントカレンダーに参加したものはいいものの
大した機能を作ったことがない筆者なので何を載せるかの時点でどうしような状態でした
いや~それにしても説明するって難しいですね・・・と改めて実感。
というか自分すら100%を理解してないですね。
いつか誰かに教える立場になったら怠慢にならないように気を付けよう・・・

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
What you can do with signing up
1