rails Ruby

【ruby】【rails】コメント投稿機能を実装する

2020年8月26日


メル○リのようなフリマアプリ制作にて、商品に対してコメント投稿機能を実装しました。その手順について解説します。ここでの目標はコメント投稿後に画面を更新するとコメントが投稿される同期通信であり、下記完成画像の非同期でコメントが反映される実装は次の記事にて紹介します。

完成画像

実装手順

以下の手順で実装していきます。
❶ DB設計
❷ Commentモデルの作成
❸ ルーティング設定
❹ Commentsコントローラの作成 / Itemsコントローラの編集
❺ コメント投稿フォームの作成
❻ コメント一覧表示欄の作成

❶ DB設計

コメント機能に関係のないテーブルは省いています。

❷ Commentモデルの作成

$ rails g model comment
マイグレーションファイル

class CreateComments < ActiveRecord::Migration[5.2]
  def change
    create_table :comments do |t|
      t.integer :user_id, null: false
      t.integer :item_id, null: false
      t.text :text, null: false
      t.timestamps
    end
  end
end
$ rails db:migrate

Commentsテーブルが作成されたか確認します。

モデルにアソシエーションの記載

app/models/comment.rb

class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :item
end

コメントは一人のユーザと一つの商品に紐づいているので、belongs_to:モデル単数形になります。

app/models/item.rb

class Item < ApplicationRecord
略
  has_many :comments, dependent: :destroy
略
end

商品は複数のコメントを所有できるので、has_many:複数形になります。

app/models/user.rb

class User < ApplicationRecord
略
  has_many :comments, dependent: :destroy
略
end

ユーザは複数のコメントを投稿できるので、has_many:複数形になります。

❸ ルーティング設定

createアクションをitemsからネストします。

config/routes.rb

resources :items do

resources :comments, only: :create

end

発行されるルーティングパスは以下の通りです。商品ごとのitem_idに紐づいたcommentsのパスになります。


Prefix Verb URI Pattern Controller#Action item_comments POST /items/:item_id/comments(.:format) comments#create

❹ Commentsコントローラの作成 / Itemsコントローラの編集


$ rails g controller comments

createアクションを設定します。

app/controllers/comments_controller.rb

class CommentsController < ApplicationController def create @item = Item.find(params[:item_id]) comment = Comment.new(comment_params) if comment.save redirect_to item_path(@item) else flash.now[:alert] = 'コメントを入力してください。' end end private def comment_params params.require(:comment).permit(:text).merge(user_id: current_user.id, item_id: params[:item_id]) end end

createアクションでcommentをDBに保存できたらitemsコントローラのshowアクションを実行するためにprefixでパス「item_path」を記述します。itemのidが必要なので、ストロングパラメータで変数commentに代入します。

今回はif文でcomment.saveしているのでオブジェクト作成だけのComment.newですが、DB保存まで行うComment.createメソッドでも作成できます。

app/controllers/items_controller.rb

def show 略 @comment = Comment.new @comments = @item.comments.order(created_at: :desc) end

comment#createにアクションを飛ばしたいので、@comment = Comment.newでインスタンスを作成します。
投稿されたコメントは降順にするためorderメソッドを使用します。

❺ コメント投稿フォームの作成

app/views/items/show.html.haml

.itemcomment__box__content
  - if current_user
    = form_with(model:[@item, @comment], class: "message-form") do |form|
      %p 相手のことを考え丁寧なコメントを心がけましょう。不快な言葉遣いなどは利用制限や退会処分となることがあります。
      = form.text_area :text, {class: "textbox"}
      %input{type:"submit", class:"form__submit", value:"コメントする"}
  - else
    %strong
      %p ※※※ コメントの投稿には新規登録/ログインが必要です ※※※

if current_userとして、ログインしていない状態では投稿フォームが表示されないようにします。

❻ コメント一覧表示欄の作成

app/views/items/show.html.haml

  .itemcomment__box__content__comment
    %p < コメント一覧 >
    - if @comments
      .itemcomment__box__content__comment__member
      - @comments.each do |comment|
        .itemcomment__box__content__comment__member__list
          = comment.user.nickname
          %strong :
          = comment.text

if @commentとして、@commentが空の場合でもエラーが起きないようにしています。

CATEGORIES & TAGS

rails, Ruby,

Author:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

むるし

インフラ系エンジニア。備忘録で色々書いていきます。
現在テックキャンプでフルコミット中。

年収訴求

CodeCamp

縛りなしWiFi

%d人のブロガーが「いいね」をつけました。