Rails コメント機能
「コメント機能」の作成
投稿された画像に対して、コメントをつけることができる機能を実装
それぞれ新たなモデルを作成し、UserモデルとPostImageモデルに関連付ける!!(1対Nの関係)
必要なファイルを準備
作成するモデル・テーブル
- PostCommentモデル
- post_commentsテーブル
作成するコントローラ
- post_commentsコントローラ
編集するファイル
- post_imagesコントローラ
- post_images/showのビュー
- ルーティング設定ファイル
コメント保存用のテーブルを設計
「誰の投稿か」「どの画像に投稿したのか」がわかるようにするため、user_idとpost_image_idを持たせる!
カラム名 | データ型 | カラムの説明 |
---|---|---|
id | integer | コメントごとのID |
comment | text | コメント本文 |
user_id | integer | コメントしたユーザのID |
post_image_id | integer | コメントされた投稿画像のID |
「PostComment」モデルを作成
rails g model PostComment comment:text user_id:integer post_image_id:integer
マイグレーションでデータベースへ反映
rails db:migrate
3つのモデルの関係性を把握
PostCommentモデルは、user_idやpost_image_idと関連付ける必要がある。
Userモデル/PostImageモデル
1人のユーザが複数の画像を投稿できる、1対Nの関係
PostImageモデル/PostCommentモデル
1つの投稿画像に対して、複数のコメントを設定できる、1対Nの関係
Userモデル/PostCommentモデル
1人のユーザが複数のコメントを行えるので、1:Nの関係
1:Nの関連付けをモデルに実装
1:Nの関係(アソシエーション)を、機能として実装する!
UserモデルとPostCommentモデルを関連付け
app/modelsフォルダのuser.rbファイル
has_many :post_comments, dependent: :destroy
dependent: :destroy
は、has_many
で使えるオプション
1:Nの関係において、「1」のデータが削除された場合、関連する「N」のデータも削除される設定!
PostImageモデルとPostCommentモデルを関連付け
app/models/post_image.rb
has_many :post_comments, dependent: :destroy
UserモデルとPostCommentモデルを関連付け
app/models/post_comment.rb
belongs_to :user
belongs_to :post_image
Controllerの作成
rails g controller post_comments
コメント投稿機能
コメント機能では投稿機能・投稿削除機能の二つを実装!
まずはコメント投稿機能から
👇
Routing
コメントは、投稿画像に対してコメントされるため、
以下のように親子関係になる!
config/routes.rb
resources :post_images, only: [:new, :create, :index, :show, :destroy] do
resources :post_comments, only: [:create]
end
このようなルーティングが作成される!
post_image_post_comments POST /post_images/:post_image_id/post_comments(.:format) post_comments#create
親のresourcesで指定したコントローラ名に、子のresourcesで指定したコントローラ名が続くURLが生成されるのが確認できる🙆🏻♀️
ネストしたURLを作成することでparams[:post_image_id]でPostImageのidが取得できるようになる!!
Controller
app/controllers/post_comments_controller.rb
def create
post_image = PostImage.find(params[:post_image_id])
comment = current_user.post_comments.new(post_comment_params)
comment.post_image_id = post_image.id
comment.save
redirect_to post_image_path(post_image)
end
private
def post_comment_params
params.require(:post_comment).permit(:comment)
end
ちなみにこの記述は
comment = current_user.post_comments.new(post_comment_params)
この記述を省略したもの
comment = PostComment.new(post_comment_params)
comment.user_id = current_user.id
コメントを投稿するためのインスタンス変数を定義
app/controllers/post_images_controller.rb
def show
@post_comment = PostComment.new
end
View
投稿画像の詳細画面で、コメントを投稿できるようにし、投稿画像へのコメント、コメント数も表示させる!
app/views/post_images/show.html.erb
<div>
<p>コメント件数:<%= @post_image.post_comments.count %></p>
<% @post_image.post_comments.each do |post_comment| %>
<p><%= image_tag post_comment.user.get_profile_image(100,100) %></p>
<%= post_comment.user.name %>
<%= post_comment.created_at.strftime('%Y/%m/%d') %><%= post_comment.comment %>
<% end %>
</div>
<div>
<%= form_with model: [@post_image, @post_comment] do |f| %>
<%= f.text_area :comment, rows: '5', placeholder: "コメントをここに" %>
<%= f.submit "送信する" %>
<% end %>
</div>
form_withに対して、[@post_image,@post_comment]のように、配列でインスタンス変数を2つ指定している点に注意
コメントは、post_imageに結びついたpost_commentであるため、2つ用意する必要があり、
post_commentをcreateするためのリクエストは、ルーティングもネスト(親子関係)しているため、上記2つの情報が必要になる!!!
コメント件数の表示を記述
2つのファイルに、コメント件数を表示する記述を追加
app/views/post_images/index.html.erb
<p><%= link_to "#{post_image.post_comments.count} コメント", post_image_path(post_image.id) %></p>
app/views/users/show.html.erb
<p><%= link_to "#{post_image.post_comments.count} コメント", post_image_path(post_image.id) %></p>
動作を確認
実際にコメントを入力して確かめる。
コメント削除機能
post_comments_controller.rbにdestroyアクションを作成していく!
Routing
config/routes.rb
resources :post_images, only: [:new, :create, :index, :show, :destroy] do
resources :post_comments, only: [:create, :destroy]
end
Controller
destoryアクションを作成
app/controllers/post_comments_conteoller.rb
def destroy
PostComment.find(params[:id]).destroy
redirect_to post_image_path(params[:post_image_id])
end
View
削除ボタンを表示させる
app/views/post_images/show.html.erb
<% if post_comment.user == current_user %>
<%= link_to "削除", post_image_post_comment_path(post_comment.post_image, post_comment), method: :delete %>
<% end %>
コメントしたものがログインユーザーのものであれば削除ボタンを表示して、削除できるようにした!
削除後は投稿詳細へリダイレクトされる🙆🏻♀️
動作を確認
コメントの削除ボタンを押して確認
応用編
空のコメントは投稿できない
モデル
validates :comment, presence: true
コメント数の表示
ビュー
コメント数: <%= @book.book_comments.count %>
投稿に対するコメント一覧を表示
ビュー
<% book.book_comments.each do |book_comment| %>
<%= book_comment.comment %>
<% end %>
自分のコメントしか削除できない
ビュー
<% if book_comment.user == current_user %>
<%= link_to "Destroy", book_book_comment_path(book, book_comment), method: :delete, class: "btn btn-danger pull-right" %>
<% end %>
コメント, コメント削除後は行う前の画面に遷移
それぞれのアクションに
redirect_to request.referer
redirect_toメソッドの一種で、このメソッドは、ユーザーが直前にアクセスしたページにリダイレクトするために使用される!
今一度コメント機能の削除について復習!
間違っているところがあればぜひ教えてください!
今日はここまで!
Discussion