##今回の課題 "フォロー機能の追加"
Railsでのフォロー機能の追加について難しかった点などを
自分で記事に書いて、頭の中を整理していこうと思います。
間違いなどありましたら、ご教授の程よろしくお願い致します。
##開発環境
ruby 2.6.3
Rails 5.2.6
Bootstrap 4.5
Cloud9
##大事なこと
今回はフォローした人とフォローする人
どちらも同じテーブル内に存在するUserです。
多くの人をフォローすることもできるし、多くの人にフォローされることもある状態なので現在は多対多の関係になっています。なので
1対Nの関係を中間テーブルを用いて関連付ける
事が重要になります。
自分自身もまだ完全には理解できていませんが、この記事を書く事で少しでも理解できる様に整理していきます。
##手順
- モデルの作成
- アソシエーション
- メソッド作成
- コントローラー
- ビュー
##モデルの作成
まずはrelationship
モデルを作成
そしてrelationshipsテーブル内のカラムに
・integer :follower_id(フォローしたUser)
・integer :followed_id(フォローされたUser)
の2つのカラムを追加します。
$ rails g model Relationship follower_id:integer followed_id:integer
$ rails db:migrate
##アソシエーション
関係性を整理すると
"1人のUserは多くの人をフォローできる"
"1人のUserは多くの人からフォローされる"
と考えると1対Nの関係性が出来上がります。
###Relationshipモデル
class Relationship < ApplicationRecord
# belongs_to :userにするとフォローするuserなの?フォローされるuserなの?となる
# このままだと存在しないテーブルを探しに行くので、class_name: で"User"を指定
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
end
###Userモデル
#foreign_keyには、@user.xxxとした際に「@user.idがfollower_idなのかfollowed_idなのか」を指定する
#フォローした人、された人の関係性を記述
has_many :relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy
has_many :reverse_of_relationships, class_name: "Relationship", foreign_key: "followed_id", dependent: :destroy
# 一覧画面で使う用の記述
# そのユーザーがフォローしている人の一覧を表示させる為
has_many :followings, through: :relationships, source: :followed
# そのユーザーがフォローされている人の一覧を表示させる為
has_many :followers, through: :reverse_of_relationships, source: :follower
続いてモデルにメソッドを記述していきます。
#フォローをした際の処理
def follow(user_id)
relationships.create(followed_id: user_id)
end
#フォローを外した時の処理
def unfollow(user_id)
relationships.find_by(followed_id: user_id).destroy
end
#フォローしているかの判別
def following?(user)
following.include?(user)
end
こう記述することでコントーローラ内の記述を見やすくする。
##Relationshipsコントローラーの作成と記述
$ rails g controller Relationships
class RelationshipsController < ApplicationController
#フォローするときの処理
def create
current_user.follow(params[:user_id])
redirect_to request.referer
end
#フォローを外す時の処理
def destroy
current_user.unfollow(params[:user_id])
redirect_to request.referer
end
#フォローの一覧画面
def followings
user = User.find(params[:user_id])
@users = user.followings
end
#フォロワーの一覧画面
def followers
user = User.find(params[:user_id])
@users = user.followers
end
end
コントローラ作成後、ルーティングも設定します。
#ネストさせる
resources :users do
resource :relationships, only:[:create, :destroy]
get "followings" => "relationships#followings", as: "followings"
get "followers" => "relationships#followers", as: "followers"
end
##ビューの記述をする
フォローボタンの設置
#もしログインユーザーがフォローしてる一覧内に、(user)が含まれていたら?
<% if current_user.followings?(user)%>
<%= link_to "フォロー外す", user_relationships_path(user.id), method: :delete %>
<% else %>
<%= link_to "フォローする", user_relationships_path(user.id), method: :post %>
<% end %>
フォロー・フォロワー一覧画面
#もしユーザーが存在したら一覧表示(usersには@変数を入れる)
<% if users.exists? %>
<% users.each do |user| %>
<table>
<thead>
<tr>
<th>name</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><%= user.name %></td>
<td>フォロー数: <%= user.followings.count %></td>
<td>フォロワー数: <%= user.followers.count %></td>
</tr>
</tbody>
</table>
<% end %>
#もしユーザーが存在しなければ
<% else %>
<p>ユーザーはいません</p>
<% end %>
あとは部分テンプレートを、render で呼び出して各ビューに貼る
##まとめ
最後の方は文章などが少なくなりましたが、記述の内容をちゃんと理解して
流れを理解できる様になればもっとわかる様になると思いました。
もっと日々勉強を続けて、スキルアップしていける様に努力します。