フォロー・フォロワー機能の実装

1.序論
学習を進めていく中で、アソシエーションが理解しづらいフォロー・フォロワー機能に関しての実装方法についてアウトプットという形で投稿します。
今回は個別で説明するよりも、まずは実装法帆をすべて説明してからどういった挙動をするか解説したいと思います。

2.環境
Rails 6.1.7
deviceによるuserモデルと本を投稿するbookモデルが存在するサンプルアプリを使用

3.モデル作成
以下のコマンドでrelationshipモデルを作成します。フォロー・フォロワーの関係は、ユーザーとユーザーで多対多の関係になりますので
中間テーブルとしてrelationshipモデルが必要となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/ea072bcc-2b98-fb0f-dc03-b12b8ca91954.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/7e5dc61a-fcf0-02bc-be6e-161177313fcc.png)
マイグレーションファイルにはフォローされているユーザー用のidであるfollower_idとフォローしているユーザー用のfollowed_idがそれぞれinteger型で定義します。記述が終わったら、rails db:migrateを忘れずに行いましょう。

4.アソシエーション
userモデルには以下のようにアソシエーションを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/27003dbf-60a5-15d0-2cc3-bbdb2b72358b.png)

relationshipsモデルには以下のようにアソシエーションを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/3a6336dc-936b-bf45-5b28-1dfcda4f9037.png)

5.ルーティング
userにネストさする形でルーティングを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/ca46faed-129d-1578-0f5e-465f03f62980.png)
忘れずにrails routesでpathを確認しておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/64c57878-11da-dc4a-25bc-983accd33f51.png)

6.フォロー機能の作成
まずはフォロー、フォロー解除用などのコントローラであるrelationshipsコントローラを作成してください。

フォローをするときにはuserモデルに新しく定義するfollowメソッドを使用します。このメソッドは、ユーザーの詳細ページで使いますので、そのユーザーのidを受け取り、user_idをfollowed_idとしてrelationshipsテーブルを作成するというメソッドになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/46610b5d-bd2a-9454-2f3d-85201ef87c0d.png)

ここで、relationshipsはフォローするときに参照するテーブルと説明しました。例えばuser_idが1の人が2,3,5,7のidのユーザーをフォローしたとすると、follower_id = 1, followed_id がそれぞれ2,3,5,7としてテーブルが作成されます。この一連の動きにより、user_id = 1が他のユーザーをフォローしたこととなります。

そしてこのfollowメソッドを使ったcreateアクションが以下に示すようになります。current_user.followという記述なので,current_userのidが外部キーであるfollower_idということになります。フォローされた2,3,5,7から見て1がフォロワーという関係ですから間違っていないと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/cfe0099c-e42e-7f10-f841-089c1ebfc262.png)

最後にviewページに記述を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/4e56662e-cf82-8225-acad-ee912f6e6245.png)

if文のcurrent_user.followings?というのはこのユーザーをフォローしているかどうかで、フォローボタンかフォロー解除ボタンを表示させています。最初の段階だとまだ誰もフォローしていないのでフォローボタンが表示されています。ボタンを押すとこのユーザーのidをコントローラに送り、createアクションによりフォローされるという仕組みになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/faa97fba-dbdb-b30f-0c5f-735a24b4bb42.png)


7.フォロー解除機能の作成
フォローを解除するときにはuserモデルに新しく定義するunfollowメソッドを使用します。このメソッドは、ユーザーの詳細ページで使いますので、そのユーザーのidを受け取り、user_idをfollowed_idとしてrelationshipsテーブルを探し、削除するというメソッドになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/9ada444f-5c31-5a15-15bb-c8c72ea47298.png)

例えばuser_idが1の人が2,3,5,7のidのユーザーをフォローを解除したとすると、follower_id = 1, followed_id がそれぞれ2,3,5,7としてテーブルが探され、それが削除されます。この一連の動きにより、user_id = 1が他のユーザーをフォロー解除したこととなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/639711db-7473-a251-b443-e8ccdccc4ebd.png)

viewに関してはフォロー機能作成のところでfollowings?メソッドがtrueだった時にボタンが表示されるギミックとなっています。

8.フォローしたユーザーとフォローされたユーザーの一覧表示機能
最後に、フォロー中のユーザーの一覧とフォロワーの一覧機能を実装します。

まずはuserモデルに以下のように記述してください。followingsの方がフォローしているユーザーを探すためのもので、viewで受け取ったユーザーidをfollower_idとしてコントローラで受け取り、sourceで定義したfolowed_idカラムを探すという動きになります。例で言いますと、user_id = 2のユーザーのフォロー一覧を探したいというときに、user_id = follower_id = 2となり、relationshipsテーブルの中でfollower_id = 2のテーブルがすべて探されます。そして、そのテーブルの中からfollowed_idの情報をすべて受け取り、それを一覧表示するという一連の動きになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/bee2d7c7-81ba-3447-96bc-294b25d63d7a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/d63663e1-d460-5d8f-b19f-8e5517ce7cad.png)

逆にフォローされているユーザーを探すときには以下のメソッドとアクションを使用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/05c3674e-bd4c-c46b-bc5c-e1a8bdbb84f2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/e2274dd0-b871-142a-58bc-672a55cff064.png)


これでフォロー・フォロワー機能を実装することができました。