📑

【Rails】いいね一覧表示機能の作り方

2023/10/05に公開

いいね一覧表示機能の作り方を解説していきます。

前提

以下のモデルが作られている前提です。

  • いいねモデル(ここではPost_favorite
  • 投稿モデル(ここではPost
  • ページネーション表示にGemのkaminariを使用

ER図

テーブルはこんな感じ。

ルーティング設定

routes.rb
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にアカウント名や名前表示を追加したければ、以下記事も参考にしてくださいね。
https://zenn.dev/ganmo3/articles/7496350e7626e5

モデル追記

Active Recordを使用していいね一覧表示取得します。
https://zenn.dev/ganmo3/articles/3d2a724e9e49ef

今回は再利用性を考慮(再利用しなかったけど)& コントローラをすっきり表示させたい という理由でPostモデルにメソッドを作りましたが、コントローラに定義しても問題ありません。

Postモデルに以下を追記します。

post.rb
# いいねをつけた投稿の取得
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

解説:

  1. selfを使ってクラスメソッドとして定義することで、同じ処理を他の場所で再利用できるようにします。()内には以下の引数を入れています。

    • user:いいね投稿を取得するための基準となるユーザー
    • page:ページネーションを使用するためのページ番号
    • per_page:1ページに表示する投稿の数
  2. includes メソッドは、関連するモデル(ここでは post_favorites)をプリロードします。これにより、後でのクエリのパフォーマンスが向上します。

includesメソッドとプリロード

プリロードとは関連するデータをあらかじめ読み込み、データベースへの余分なクエリを避けることでパフォーマンスを向上させる方法のこと。

例えば、ユーザーが投稿したすべての投稿を表示する場合、通常は次のようなステップがある:

  1. ユーザー情報を取得するためのクエリを発行。
  2. ユーザーが投稿した投稿のIDを取得するためのクエリを発行。
  3. 各投稿の詳細情報を取得するためのクエリを、投稿の数だけ発行。

このように、通常の方法では3つのクエリが必要で、データベースへのアクセスが多くなります。しかし、プリロードを使用することで、これらの余分なクエリを回避できます。

具体的には、プリロードを使用すると、以下のようになります:

  1. ユーザー情報を含むクエリを発行(これは通常通りのクエリです)。
  2. ユーザーが投稿した投稿のIDを取得するためのクエリも発行します(これも通常通りのクエリです)。
  3. ここでプリロードが活躍します。プリロードは、事前に取得した投稿の詳細情報を一度に取得します。つまり、投稿の数だけではなく、一括でデータを取得します。これにより、余分なクエリが発行されず、データベースへのアクセスが最小限に抑えられます。

以下記事も参考にしてくださいね
https://zenn.dev/ganmo3/articles/a4b2204088d7de

  1. where メソッドは、条件に一致するデータを絞り込むために使用されます。この場合、post_favorites テーブルで user_id が指定した user.id と一致する行を選択します。つまり、ユーザーがいいねした投稿を取得します。

  2. order メソッドは、取得したデータを指定したカラム(ここでは created_at)の値でソートします。created_at: :desc は、作成日時を降順にソートさせます。

  3. page メソッドは、ページネーションのために指定されたページに表示するデータを選択します。ページ番号は page メソッドに渡された page パラメータによって決定します。

  4. per メソッドは、ページごとのデータ数を指定します。per_page パラメータに渡された値に基づいてデータを分割します。

コントローラ呼び出し

作ったメソッドを以下のようにユーザーコントローラから呼び出します。

users_controller.rb
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件の表示にしています。

ビュー作成

あとはアプリケーションに合わせてビューを作成するだけ!
以下は参考までに。

public/users/liked_posts.html.erb
<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>

ヘッダーにリンクを入れています。

_header.html.erb
:
<li><%= link_to liked_posts_user_path(current_user), data: { "turbolinks" => false } do %><i class="fas fa-thumbs-up"></i>いいねした投稿<% end %></li>
:

Discussion