コメント一覧表示機能を実装しよう

学習の目標

本章では、以下の内容を学習します。

  • 投稿詳細ページにコメント一覧を表示する方法を理解する
  • 関連データの取得ソートの実装方法を習得する
  • 条件分岐を使った表示制御の方法を学ぶ
  • コメント表示のスタイリングとユーザーインターフェースの改善方法を理解する

はじめに

前回のレッスンでは、コメント投稿機能を実装しました。ユーザーがコメントを投稿できるようになりましたが、まだそれらのコメントを表示する機能がありません。そのため、投稿したコメントが実際にどこに保存されているのか、ユーザーには見えない状態です。

今回は、投稿詳細ページにコメント一覧を表示する機能を実装します。これにより、ユーザーは投稿に対する他のユーザーのコメントを閲覧できるようになり、コミュニケーション機能が実質的に機能し始めます。

コメント一覧表示では、以下の要素を考慮するようにしましょう。

  1. コメントの並び順 - 通常は最新のコメントが上に表示されるようにします
  2. コメントがない場合の表示 - 「まだコメントはありません」のようなメッセージを表示します
  3. コメントのメタデータ - 投稿者名や投稿日時などの情報を表示します
  4. 全体的なレイアウトとデザイン - 読みやすく、見た目も美しいデザインを目指します

これらの要素を考慮しながら、実装を進めていきます。特に、コメントの表示順やデザインはユーザーエクスペリエンスに大きな影響を与えるため、慎重に設計する必要があります。

それでは、具体的なコードと共に実装を進めていきましょう。

投稿詳細ページの修正

まず、投稿詳細ページにコメント一覧を表示するセクションを追加します。前回のレッスンでは、コメントフォームの下に「ここにコメント一覧を表示」というコメントを残していましたが、今回はその部分に実際のコメント一覧を実装します。

app/views/posts/show.html.erb を開き、コメントフォームセクションの後にコメント一覧セクションを追加してください。

<!-- 既存のコメントフォームセクションの後に追加 -->
<!-- コメント一覧 -->
<div class="bg-white p-6 shadow rounded mb-7">
<h4 class="text-lg font-medium text-gray-800 mb-4">コメント一覧</h4>
<% if @post.comments.empty? %>
<p class="text-gray-500 text-center py-4">まだコメントはありません。最初のコメントを投稿してみましょう!</p>
<% else %>
<div class="space-y-4">
<% @post.comments.order(created_at: :desc).each do |comment| %>
<div class="border-b border-gray-200 pb-4 last:border-b-0 last:pb-0">
<p class="text-sm text-gray-500">
<%= link_to comment.user.nickname, user_path(comment.user), class: "font-medium text-indigo-600 hover:text-indigo-800" %>
<span class="mx-1"></span>
<span><%= comment.created_at.strftime("%Y年%m月%d日 %H:%M") %></span>
</p>
<p class="mt-2 text-gray-700"><%= comment.content %></p>
</div>
<% end %>
</div>
<% end %>
</div>

このコードについて、重要な部分を詳しく見ていきましょう。

コメントの有無による条件分岐

<% if @post.comments.empty? %>
<p class="text-gray-500 text-center py-4">まだコメントはありません。最初のコメントを投稿してみましょう!</p>
<% else %>
<!-- コメント一覧表示 -->
<% end %>

まず、@post.comments.empty? を使って投稿に紐づくコメントがあるかどうかをチェックしています。コメントがない場合は、「まだコメントはありません。最初のコメントを投稿してみましょう!」というメッセージを表示します。

これは、コメントがない状態でも画面が寂しくならないようにするための工夫です。また、ユーザーに対してコメント投稿を促す効果もあります。

コメントの並び順

<% @post.comments.order(created_at: :desc).each do |comment| %>

コメントの表示には order(created_at: :desc) を使用して、作成日時の降順(最新のものが上)に並べています。これにより、最近投稿されたコメントが上に表示されるため、ユーザーは新しい情報をすぐに確認できます。

ソーシャルメディアでは、コメントの並び順は重要な要素です。最新のものが上に表示される方式と、古いものが上に表示される方式がありますが、今回は一般的な「最新順」を採用しています。

コメントの表示

<div class="border-b border-gray-200 pb-4 last:border-b-0 last:pb-0">
<p class="text-sm text-gray-500">
<%= link_to comment.user.nickname, user_path(comment.user), class: "font-medium text-indigo-600 hover:text-indigo-800" %>
<span class="mx-1"></span>
<span><%= comment.created_at.strftime("%Y年%m月%d日 %H:%M") %></span>
</p>
<p class="mt-2 text-gray-700"><%= comment.content %></p>
</div>

各コメントは、投稿者情報、投稿日時、コメント内容を含む div 要素で表示しています。デザイン的には、下部に境界線を設けることで各コメントを視覚的に区切っています。ただし、最後のコメントの下には境界線を表示しないように last:border-b-0 last:pb-0 というTailwind CSSのクラスを使用しています。

投稿者のニックネームはクリック可能なリンクになっており、そのユーザーのページに遷移できます。これにより、コメントからユーザープロフィールへの自然な導線が確保されます。

投稿日時は strftime メソッドを使用して、日本の一般的な形式(年月日 時分)でフォーマットしています。これにより、いつコメントが投稿されたのかが一目でわかります。

全体的なデザイン

コメント一覧全体は、白い背景に影をつけたカード状のデザインになっています。これは、コメントフォームや投稿詳細のデザインと統一感を持たせるためです。

<div class="bg-white p-6 shadow rounded mb-7">
<h4 class="text-lg font-medium text-gray-800 mb-4">コメント一覧</h4>
<!-- コメント一覧の内容 -->
</div>

「コメント一覧」という見出しを付けることで、このセクションが何を表示しているのかを明確にしています。また、コメント同士の間には適切な余白(space-y-4)を設けることで、視認性を高めています。

実装の方法について補足

今回、コメント一覧の表示は、ビュー内で直接 @post.comments を使用して行っています。これは、RailsのActiveRecordが提供するリレーション機能を利用して、投稿に紐づくコメントを簡単に取得できるためです。

@post.comments.order(created_at: :desc)

ただし、より大規模なアプリケーションや、パフォーマンスが重要な場合には、コントローラーでコメントをあらかじめ取得しておくようなやり方もあります。例えば、PostsControllershow アクションで以下のようにコメントを取得しておく方法です。

def show
@post = Post.find_by(id: params[:id])
@comment = Comment.new
@comments = @post.comments.order(created_at: :desc).includes(:user)
end

このように includes(:user) を使用すると、 N+1 クエリ問題を回避できます。

N+1クエリ問題とは、リレーション先のデータを取得するために、不必要に多くのデータベースクエリが発行される問題です。 例えば、コメントが多くなると、各コメントの投稿者情報を取得するために、コメントの数だけ追加でデータベースへの問い合わせが発生します。これにより、パフォーマンスが低下する可能性があります。

この問題を解決するために、includes(:user) を使用して、コメントとその投稿者情報を一度のクエリで取得することができます。これにより、データベースへの問い合わせ回数を減らし、パフォーマンスを向上させることができます。

しかし、今回の実装ではシンプルさを重視して、ビュー内でコメントを取得する方法を採用しました。

実際の現場では、includes を使ってパフォーマンスを最適化することが一般的ですが、学習段階ではこのようなシンプルな実装から始めるのも良いでしょう。

動作確認

実装が完了したら、実際にコメント一覧表示機能が動作するか確認しましょう。

$ bin/dev

ブラウザで投稿詳細ページにアクセスし、以下の点を確認してください。

  1. コメントがない場合、「まだコメントはありません」というメッセージが表示されるか
  2. コメントを投稿すると、コメント一覧に表示されるか
  3. 最新のコメントが上に表示されるか
  4. 投稿者のニックネームがリンクになっているか
  5. 投稿日時が正しく表示されるか
  6. 複数のコメントを投稿した場合、すべて表示されるか

以下のスクリーンショットのように、コメント一覧が正しく表示されていることを確認できればOKです。

コメント一覧表示の確認

変更をコミット

ここまでの変更をコミットしておきましょう。

$ git add .
$ git commit -m "コメント一覧表示機能を実装"
$ git push

まとめ

本章では、投稿詳細ページにコメント一覧を表示する機能を実装しました。具体的には、以下の内容を実装しました。

  • コメントを作成日時の降順で表示するリスト
  • コメントがない場合の代替テキスト表示
  • コメントの投稿者投稿日時のメタデータ表示
  • 統一感のある視覚的なデザイン

これにより、ユーザーは投稿に対するコメントを閲覧できるようになり、アプリケーションのソーシャル機能が実質的に機能し始めました。ユーザー同士が互いのコメントを確認できることで、コミュニケーションの活性化が期待できます。

コメント投稿機能とコメント一覧表示機能を組み合わせることで、ユーザー間の対話が可能になりました。

しかし、まだコメントを削除したり編集したりする機能がありません。次のレッスンでは、コメント削除機能を実装して、ユーザーが自分のコメントを管理できるようにしていきましょう。

この先のレッスンでは、さらにコメント機能を拡張して、より使いやすいコミュニケーション機能を実現していきます。

このセクションは有料サブスクリプションへの登録、またはログインが必要です。完全なコンテンツにアクセスするには、料金ページ(/pricing)をご覧ください。購入済みの場合は、ログインしてください。

Basicプランでより詳しく学習

この先のコンテンツを読むにはBasicプラン以上が必要です。より詳細な解説、実践的なサンプルコード、演習問題にアクセスして学習を深めましょう。

作成者:とまだ
Previous
コメント投稿機能を実装しよう