0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rails コメント機能の作り方

Last updated at Posted at 2025-06-02

はじめに

この記事はプログラミング初学者が他の記事を参考にしたり、実際に実装してみたりして、アウトプットの一環としてまとめたものです。内容に不備などあればご指摘いただますと幸いです。

今回Xクローン作成中にコメント機能を実装しました。
そのコメント機能について備忘録も兼ねて記事を作成していきます。

実現したいこと

投稿されたツイートに対して、コメントをつけることができる機能を実装すること。

コメント機能について

コメントする時のイメージ

comment_1.png
  • ①のユーザーに注目すると、1人のユーザーから複数の線が伸びています。
    → つまりユーザーは「たくさんのツイートにコメント」することができます。
  • ②のツイートに注目すると、1つのツイートから複数の線が伸びています。
    →つまりツイートは「たくさんのユーザーにコメント」されます。

このように 「ユーザーもツイートもたくさん持っている」関係を多対多(M:N)の関係 といいます。
そして、多対多(M:N)の関係には中間テーブルが必要!

中間テーブルを用いてER図を表すと

comment_erd.png

このようになります。

Commentモデルとテーブルの作成

それでは、実装していきましょう!
以下のコマンドでモデルを作成します。

$ rails g model comment user_id:integer tweet_id:integer content:text

マイグレーションファイルは以下のように生成されます。

app/model/migrate/○○○_create_comments.rb
class CreateComments < ActiveRecord::Migration[7.0]
  def change
    create_table :comments do |t|
      t.integer :user_id
      t.integer :tweet_id
      t.text :content

      t.timestamps
    end
  end
end

以下のコマンドでマイグレーションを実行しましょう。

$ rails db:migrate

アソシエーションの設定

それぞれのファイルに以下を追加します。

app/models/comment.rb
  belongs_to :user
  belongs_to :tweet
app/models/user.rb
has_many :comments, dependent: :destroy
app/models/tweet.rb
has_many :comments, dependent: :destroy

dependent: :destroyは、has_manyで使えるオプションです。
1:Nの関係において、「1」のデータが削除された場合、関連する「N」のデータも削除される設定。
ここでは、ツイートが削除された場合に関連するコメントも削除されるように設定してます。

ルーティングの設定

コメントは、ツイートに対して、コメントするのでネストしたルーティングを作成します。

config/routes.rb
resources :tweets do
  resources :comments, only: [:create]
end

ルーティングを見てみると
comment_2.png

こんな感じで作成されます。
また、ネストしたルーティングを作成したことでtweet_idparams[:tweet_id]で取得できます。

Controllerの作成

以下のコマンドでコントローラを作成します。

$ rails g controller comments

生成されたコントローラのファイルを以下のように編集します。

app/controllers/comments_controller.rb
class CommentsController < ApplicationController
  def create
    @tweet = Tweet.find(params[:tweet_id])
    # @tweetに関連したCommentクラスの新しいインスタンスを作成。
    # つまり、comment.tweet_id = @tweet.idが済んだ状態で生成されている。
    # buildはnewと同じ意味で、アソシエーションしながらインスタンスをnewする時に形式的に使われる。
    @comment = @tweet.comments.build(comment_params)
    # コメントの所有者を現在ログインしているユーザーに設定。
    @comment.user_id = current_user.id
    @comment.save
    # 直前のページにリダイレクトする。
    redirect_to request.referer, notice: 'コメントをしました。'
  end

  private

  def comment_params
    params.require(:comment).permit(:content, images: [])
  end
end

コメントを投稿するためのインスタンス変数を定義

app/controllers/tweets_controller.rb
def show
  @tweet = Tweet.find(params[:id])
  @comments = @tweet.comments.order(created_at: 'DESC')
  @comment = current_user.comments.new # 追加
end

Viewの作成

ツイートの詳細画面でコメントを投稿できるようにします。

app/views/tweets/show.html.slim
= form_with model: [@tweet, @comment], url: tweet_comments_path(@tweet) do |f|
  = f.text_area :content, class: "post-content", placeholder: "返信をポスト" # テキスト投稿フォームを作成。
  div.d-flex.justify-content-between.pt-2.pb-2
    ul.post-icon-list.d-flex
      li.ms-2
        div
          = f.label :images
            i.bi.bi-card-image style="cursor: pointer"
            = f.file_field :images, multiple: true, style: "display: none" #投稿画像のファイル選択ボックスを作成。Bootstrapを用いてfile_fieldの見た目をアイコンにしてます。
      li
        div
        i.bi.bi-filetype-gif
      li
        div
        i.bi.bi-emoji-smile
      li
        div
        i.bi.bi-geo-alt
    div
      = f.submit "返信", class: "post-btn" # 送信ボタンを作成。

form_withを記述する際、ルーティングでネストを定義している時は[@post, @comment]のように、配列で二つ ([関連元のインスタンス, 関連先のインスタンス]) 渡す必要があります。

おわりに

最後まで読んでいただきありがとうございました。
少しでも皆さんの参考になれば幸いです。

参考にしたサイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?