🐈
【Rails】 コメント機能
🍍今回の流れ
完成図
モデル
- 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