🐈

【Rails】 コメント機能

2023/08/10に公開

🍍今回の流れ

完成図

https://www.loom.com/share/fce3ec1ce58d4582bc5feac5fca7d853?sid=fc1c26e4-2bff-4e2b-981a-ffb7eb2b4349

モデル

  • book_commentモデルを追加
  • 空のコメントは保存できない

コントローラー

  • book_commentsコントローラを追加
  • createアクションを追加
  • destroyアクションを追加
  • 自分のコメントしか削除できないこと
  • コメント、 コメント削除後は行う前の画面に遷移する

ビュー

  • 投稿一覧画面にコメント数を追加➀
  • 投稿詳細画面に投稿に対するコメント一覧、 コメント数を追加➁
  • ユーザー詳細画面に、コメント数を追加➂

🍍作成

モデル

book_commentモデルを追加

ターミナル
rails g model BookComment comment:text user_id:integer book_id:integer

上記コマンドを実行するとマイグレーションファイルに直接書き込まなくてもOK

カラム名 データ型 カラムの説明
id integer コメントごとのID
comment text コメント本文
user_id integer コメントしたユーザーのID
book_id integer コメントされた投稿のID
ターミナル
rails db:migrate

いいね機能導入時と考え方は一緒!

  • BookCommentモデル
コメントあり
models/books_comment.rb
class BookComment < ApplicationRecord
    belongs_to :user
    belongs_to :book
    
    validates :comment, presence: true
end
models/books_comment.rb
class BookComment < ApplicationRecord
    belongs_to :user
    belongs_to :book
   # belongs_toで1:Nを関連付ける
    validates :comment, presence: true
   # 空のコメントが保存されないようにバリデーションを定義する
end
  • Userモデル
コメントなし
models/user.rb
class User < ApplicationRecord
 has_many :book_comments, dependent: :destroy
end
models/user.rb
class User < ApplicationRecord
 has_many :book_comments, dependent: :destroy
 #複数のBookComentと関連付ける
 #userが消されたとき関連するBookComentも同時に消される
end
  • Bookモデル
コメントなし

``rb:models/book.rb
class Book < ApplicationRecord
has_many :book_comments, dependent: :destroy
end

models/book.rb
class Book < ApplicationRecord
 has_many :book_comments, dependent: :destroy
 #複数のBookComentと関連付ける
 #bookが消されたとき関連するBookComentも同時に消される
end

has_manyとbelongs_toの両方が設定されることで、1:Nの関係が成立する!(上の図belongにs付け忘れてます😢)

ルーティング

config/routes.rb
Rails.application.routes.draw do
 :
  resources :books, only: [:index, :show, :edit, :create, :destroy, :update] do
+   resources :book_comments, only: [:create, :destroy]
    resource :favorites, only: [:create, :destroy]
  end
  resources :users, only: [:index, :show, :edit, :update]
end

いいね機能と同様にbooksにネスト(親子関係を築く)する。

  • コメントは特定の投稿に紐付いていており、投稿の下にコメントが追加されていく形で表示・操作をおこないたいから!

コメントは1つの本に対して何個でも投稿してよいものとするのでresourcesと記述する。(s)を付ける!!

コントローラー作成

ターミナル
rails g controller book_comments
controllers/books_comments_controller.rb
class BookCommentsController < ApplicationController
 def create
   book = Book.find(params[:book_id])
   comment = current_user.book_comments.new(book_comment_params)
   comment.book_id = book.id
   comment.save
   redirect_to request.referer
 end
 
 def destroy
   comment = BookComment.find(params[:id])
   comment.destroy
 end
 
 private
 
 def book_comment_params
   params.require(:book_comment).permit(:comment)
 end
end

comment = current_user.post_comments.new(post_comment_params)comment = PostComment.new(post_comment_params)comment.user_id = current_user.idが一文にまとめられた記述。

💎comment.book_id = book.idを記述しなきゃいけないのなんで?
モデルで関連づけしてるからこれをわざわざ記述する必要あるの?

controllers/books_controller.rb
def show
  @book_comment = BookComment.new
end

今回は、本の詳細ページにコメント投稿フォームを表示させたいのでshowアクションに記述を追加する。

ビュー

コメント入力フォーム(テンプレート)

views/book_comments/_form.html.erb
<%= form_with model: [book, book_comment] do |f| %>
  <%= f.text_area :comment,  placeholder: "コメントをここに" %>
  <%= f.submit "送信" %>
<% end %>

コメント一覧(テンプレート)

views/bool_comments/_index.html.erb
<table>
  <tbody>
    <% book.book_comments.each do |book_comment| %>
    <tr>
      <td>
        <%= link_to user_path(book_comment.user) do %>
          <%= image_tag book_comment.user.get_profile_image, size: "50x50" %><br>
          <%= book_comment.user.name %>
        <% end %>
      </td>
      <td><%= book_comment.comment %></td>
      <td>
        <% if book_comment.user == current_user %>
          <%= link_to "Destroy", book_book_comment_path(book, book_comment), method: :delete, class: "btn btn-sm btn-danger float-end" %>
        <% end %>
      </td>
    </tr>
    <% end %>
  </tbody>
</table>

showページにテンプレートの呼び出し

views/book/show.html.erb
<%= render "book_comments/index", book: @book %>
<%= render "book_comments/form", book: @book, book_comment: @book_comment %>

コメント数の表示

  <td>コメント数: <%= @book.book_comments.count %></td>

Discussion