Comment モデルとコントローラーを作成しよう

学習の目標

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

  • コメント機能の概要と役割を理解する
  • Comment モデルをデータベース設計に基づいて作成する
  • 多対多のリレーションを正しく設定する方法を習得する
  • CommentsController の基本構造を実装する

はじめに

TechLog アプリケーションに新たな機能を追加していきましょう。今回は「コメント機能」を実装します。これにより、ユーザーは学習ログに対してコメントを残すことができるようになり、他のユーザーとのコミュニケーションが可能になります。

コメント機能の実装では、複数のモデル間の関連付け(リレーション)が重要になります。投稿(Post)とユーザー(User)の両方に関連するコメント(Comment)を作成することで、「誰が」「どの投稿に」コメントしたのかを管理できるようになります。

それでは、まずはコメント機能の土台となる Comment モデルとコントローラーを作成していきましょう。

Comment モデルの作成

最初に、Comment モデルを作成します。Comment モデルは、コメントの内容(content)と、そのコメントを投稿したユーザー(user_id)、コメント先の投稿(post_id)を関連付けるためのモデルです。

ターミナルで以下のコマンドを実行して、モデルを生成します。

$ bin/rails g model Comment content:text user:references post:references
invoke active_record
create db/migrate/20250611151748_create_comments.rb
create app/models/comment.rb
invoke rspec
create spec/models/comment_spec.rb
invoke factory_bot
create spec/factories/comments.rb

このコマンドにより、以下のものが生成されます。

  1. マイグレーションファイル - コメントテーブルを作成するための設計図
  2. Comment モデル - コメントの動作を定義するファイル
  3. テスト関連ファイル - モデルのテストを書くためのファイル

生成されたマイグレーションファイル(db/migrate/YYYYMMDDHHMMSS_create_comments.rb)の内容を確認してみましょう。

class CreateComments < ActiveRecord::Migration[8.0]
def change
create_table :comments do |t|
t.text :content
t.references :user, null: false, foreign_key: true
t.references :post, null: false, foreign_key: true
t.timestamps
end
end
end

上記のような内容になっているはずです。このマイグレーションファイルは、コメントを保存するための comments テーブルを作成します。

このマイグレーションファイルでは、以下のカラムを持つ comments テーブルを作成します。

  • content - コメントの内容を保存するテキスト型のカラム
  • user_id - コメントを投稿したユーザーを参照する外部キー
  • post_id - コメント先の投稿を参照する外部キー
  • created_at, updated_at - 作成日時と更新日時(t.timestamps で自動生成)

references 型を使用することで、外部キーとインデックスが自動的に設定されます。これにより、データベースレベルでの関連付けが効率的に行われます。

次に、生成された Comment モデル(app/models/comment.rb)を確認します。

class Comment < ApplicationRecord
belongs_to :user
belongs_to :post
end

モデルファイルには既に belongs_to 関連付けが設定されています。これは、コメントが必ずひとつのユーザーとひとつの投稿に属することを示しています。

User モデルと Post モデルの修正

Comment モデルを作成したら、既存の User モデルと Post モデルにも関連付けを追加する必要があります。これにより、ユーザーや投稿から関連するコメントを簡単に取得できるようになります。

まず、User モデル(app/models/user.rb)を次のように修正します。

class User < ApplicationRecord
has_many :posts # 既存の関連付け
has_many :comments # 追加する関連付け
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :nickname, presence: true, length: { maximum: 20 }
end

次に、Post モデル(app/models/post.rb)も同様に修正します。

class Post < ApplicationRecord
belongs_to :user
has_many :comments # 追加する関連付け
validates :title, presence: true, length: { maximum: 100 }
validates :content, presence: true, length: { maximum: 1000 }
end

has_many 関連付けを追加することで、ユーザーや投稿に紐づく複数のコメントを取得できるようになります。例えば、user.comments でそのユーザーが投稿した全てのコメントを、post.comments でその投稿に対する全てのコメントを取得できます。

マイグレーションの実行

モデルの設定が完了したら、マイグレーションを実行してデータベースにコメントテーブルを作成します。

$ bin/rails db:migrate
== 20250611151748 CreateComments: migrating ===================================
-- create_table(:comments)
-> 0.0022s
== 20250611151748 CreateComments: migrated (0.0023s) ==========================

テスト環境のデータベースにも同様にマイグレーションを適用します。

(カリキュラム内ではコメント機能のテストは行いませんが、テスト環境のデータベースも更新しておくことは良い習慣です。)

$ RAILS_ENV=test bin/rails db:migrate
== 20250611151748 CreateComments: migrating ===================================
-- create_table(:comments)
-> 0.0006s
== 20250611151748 CreateComments: migrated (0.0007s) ==========================

これでデータベース側の準備は完了です。

Comments コントローラーの作成

次に、コメントを操作するための CommentsController を作成します。ターミナルで以下のコマンドを実行します。

$ bin/rails g controller comments create destroy edit update
create app/controllers/comments_controller.rb
route get "comments/create"
get "comments/destroy"
get "comments/edit"
get "comments/update"
invoke tailwindcss
create app/views/comments
create app/views/comments/create.html.erb
create app/views/comments/destroy.html.erb
create app/views/comments/edit.html.erb
create app/views/comments/update.html.erb
invoke rspec
create spec/requests/comments_spec.rb
create spec/views/comments
create spec/views/comments/create.html.tailwindcss_spec.rb
create spec/views/comments/destroy.html.tailwindcss_spec.rb
create spec/views/comments/edit.html.tailwindcss_spec.rb
create spec/views/comments/update.html.tailwindcss_spec.rb

このコマンドにより、CommentsController とそれに対応するビューファイルが生成されます。ただし、create および destroy アクションに対応するビューファイルは実際には使用しないので、削除しておきます。

$ rm app/views/comments/create.html.erb
$ rm app/views/comments/destroy.html.erb
$ rm app/views/comments/update.html.erb

また、詳しくは後述しますが、コメント機能についてはテストは省略する方針で進めますので、テストファイルもまとめて削除しておきます。

もし後にご自身でチャレンジしてみたい場合は、テストファイルを残しておいても構いません。

$ rm spec/requests/comments_spec.rb
$ rm -rf spec/views/comments
$ rm spec/models/comment_spec.rb

次に、生成されたルーティングを削除します。CommentsController 用のルーティングは次のレッスンで別の形式で設定するため、今回生成された get ルーティングは不要です。

config/routes.rb ファイルを開き、以下の行を削除します。

# 以下の4行はまとめて削除します
get "comments/create"
get "comments/destroy"
get "comments/edit"
get "comments/update"

最後に、CommentsController の基本構造を整えます。app/controllers/comments_controller.rb を以下のように修正します。

class CommentsController < ApplicationController
before_action :authenticate_user!
before_action :set_post
def create
# 実装は次のレッスンで行います
end
def edit
# 実装は後のレッスンで行います
end
def update
# 実装は後のレッスンで行います
end
def destroy
# 実装は後のレッスンで行います
end
private
def set_post
@post = Post.find(params[:post_id])
end
def comment_params
params.require(:comment).permit(:content)
end
end

それぞれ、おさらいも含めて簡単に説明しておきましょう。

  • before_action :authenticate_user! - コメント機能はログインユーザーのみが使用できるよう制限
  • before_action :set_post - コメント対象の投稿を特定するためのヘルパーメソッド
  • private メソッド - コントローラー内で使用する共通メソッドとストロングパラメータの設定

これまでのレッスンで学んだ内容を思い出せましたでしょうか?

before_actionprivate メソッドの使い方、ストロングパラメータの設定方法などは Rails の基本的な書き方です。

逆に言えば、これらの基本的な構造を理解していれば、コントローラーの実装はスムーズに進められるはずですので、しっかりと復習しておきましょう。

アクション内の実際の処理は、この後のレッスンで段階的に実装していきます。

テストに関する補足

ここまでのレッスンでは、RSpec を使用してモデルやコントローラーのテストを行う準備を進めてきました。

しかし、コメント機能の実装に関しては、特にコントローラーのアクションが複雑になってくるため、RSpec テストも同時に作っていこうとすると、理解が難しくなる可能性があります。

そのため、ここからはあえて RSpec のテストコードを省略し、実装に集中して進めていきます。 もちろん、テストを書くことは非常に重要なことですが、今回はまず実装を優先し、後で動作確認を行いながら動作確認をカバーしていく方針で進めます。

変更をコミット

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

$ git add .
$ git commit -m "Comment モデルとコントローラーを作成"
$ git push

まとめ

本章では、コメント機能の土台となる Comment モデルと CommentsController を作成しました。具体的には、以下の内容を実装しました。

  • Comment モデルの作成と必要なカラムの設定
  • User モデルと Post モデルとのリレーションの設定
  • CommentsController の基本構造の実装

これで、コメント機能を実装するための基礎ができました。次のレッスンでは、コメント機能のためのルーティング設定を行い、実際にコメントを投稿できるようにしていきます。

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

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

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

作成者:とまだ
Previous
コメント機能を追加しよう