【Rails】いいね一覧表示機能の作り方
いいね一覧表示機能の作り方を解説していきます。
前提
以下のモデルが作られている前提です。
- いいねモデル(ここでは
Post_favorite
) - 投稿モデル(ここでは
Post
) - ページネーション表示にGemの
kaminari
を使用
ER図
テーブルはこんな感じ。
ルーティング設定
resources :users, param: :account, only: [:show, :edit, :update] do
member do
# いいねした一覧
get :liked_posts
:
end
解説:
- 個別のリソース(ここではユーザー)に対するアクションなのでmemberブロックを使用。
-
liked_posts
アクションを追加し、ユーザーごとの「いいね」した投稿を表示するようにします。
つまり、このルート設定で、/users/:account/liked_posts
のURLで特定のユーザーが「いいね」した投稿の一覧を表示できるようになります。
俺の場合は、param
オプションを使っていますが、これは使っていなくてももちろん大丈夫です。
URLにアカウント名や名前表示を追加したければ、以下記事も参考にしてくださいね。
モデル追記
Active Recordを使用していいね一覧表示取得します。
今回は再利用性を考慮(再利用しなかったけど)& コントローラをすっきり表示させたい という理由でPost
モデルにメソッドを作りましたが、コントローラに定義しても問題ありません。
Postモデルに以下を追記します。
# いいねをつけた投稿の取得
def self.liked_posts(user, page, per_page) # 1. モデル内での操作を開始
includes(:post_favorites) # 2. post_favorites テーブルを結合
.where(post_favorites: { user_id: user.id }) # 3. ユーザーがいいねしたレコードを絞り込み
.order(created_at: :desc) # 4. 投稿を作成日時の降順でソート
.page(page) # 5. ページネーションのため、指定ページに表示するデータを選択
.per(per_page) # 6. ページごとのデータ数を指定
end
解説:
-
self
を使ってクラスメソッドとして定義することで、同じ処理を他の場所で再利用できるようにします。()内には以下の引数を入れています。-
user
:いいね投稿を取得するための基準となるユーザー -
page
:ページネーションを使用するためのページ番号 -
per_page
:1ページに表示する投稿の数
-
-
includes
メソッドは、関連するモデル(ここではpost_favorites
)をプリロードします。これにより、後でのクエリのパフォーマンスが向上します。
includesメソッドとプリロード
プリロードとは関連するデータをあらかじめ読み込み、データベースへの余分なクエリを避けることでパフォーマンスを向上させる方法のこと。
例えば、ユーザーが投稿したすべての投稿を表示する場合、通常は次のようなステップがある:
- ユーザー情報を取得するためのクエリを発行。
- ユーザーが投稿した投稿のIDを取得するためのクエリを発行。
- 各投稿の詳細情報を取得するためのクエリを、投稿の数だけ発行。
このように、通常の方法では3つのクエリが必要で、データベースへのアクセスが多くなります。しかし、プリロードを使用することで、これらの余分なクエリを回避できます。
具体的には、プリロードを使用すると、以下のようになります:
- ユーザー情報を含むクエリを発行(これは通常通りのクエリです)。
- ユーザーが投稿した投稿のIDを取得するためのクエリも発行します(これも通常通りのクエリです)。
- ここでプリロードが活躍します。プリロードは、事前に取得した投稿の詳細情報を一度に取得します。つまり、投稿の数だけではなく、一括でデータを取得します。これにより、余分なクエリが発行されず、データベースへのアクセスが最小限に抑えられます。
以下記事も参考にしてくださいね
-
where
メソッドは、条件に一致するデータを絞り込むために使用されます。この場合、post_favorites
テーブルでuser_id
が指定したuser.id
と一致する行を選択します。つまり、ユーザーがいいねした投稿を取得します。 -
order
メソッドは、取得したデータを指定したカラム(ここではcreated_at
)の値でソートします。created_at: :desc
は、作成日時を降順にソートさせます。 -
page
メソッドは、ページネーションのために指定されたページに表示するデータを選択します。ページ番号はpage
メソッドに渡されたpage
パラメータによって決定します。 -
per
メソッドは、ページごとのデータ数を指定します。per_page
パラメータに渡された値に基づいてデータを分割します。
コントローラ呼び出し
作ったメソッドを以下のようにユーザーコントローラから呼び出します。
def liked_posts
@liked_posts = Post.liked_posts(current_user, params[:page], 12)
end
解説:
-
Post.liked_posts
:Postモデルからliked_posts
メソッドを呼び出します。 -
(current_user, params[:page], 12)
:liked_posts
メソッドに渡される引数です。1ページあたり12件の表示にしています。
ビュー作成
あとはアプリケーションに合わせてビューを作成するだけ!
以下は参考までに。
<div class="container">
<div class="row">
<div class="col-md-12">
<h4 class="headline mt-5 ml-5">いいねした投稿</h4>
<div class="row mt-3">
<% @liked_posts.each do |post| %>
<%= render 'public/shared/post_item', post: post %>
<% end %>
</div>
<div class="d-flex justify-content-center">
<%= paginate @liked_posts, theme: 'bootstrap-5' %>
</div>
</div>
</div>
</div>
ヘッダーにリンクを入れています。
:
<li><%= link_to liked_posts_user_path(current_user), data: { "turbolinks" => false } do %><i class="fas fa-thumbs-up"></i>いいねした投稿<% end %></li>
:
Discussion