はじめに
記事投稿アプリの記事に対して、コメントを作れる機能を実装した。
さらに、編集と削除ができるようにしたい。
前提
下記は作成済み
投稿機能
ユーザーテーブル
コメントテーブル
コメントコントローラー createアクション
下記テーブルは作成済み。
No | 項目 | 内容 |
---|---|---|
1 | OS | Mac |
2 | Ruby | 2.6.3 |
3 | rails | 6.0.4 |
ポイント
・コメント投稿機能とeditテンプレートを同じパーシャルを適用することで、dryにする。
・post_controllerに@commentを追加した。
post/show.html.erbテンプレートからコメントをする際に、
/posts/:post_id/comments/:id/edit にアクセスする時に使用するcommentモデルの主idを取得するため。
・コメントを編集、削除機能のパーシャルを作成する。
ログインユーザーがコメント作成者なら編集と削除を実行可能。
ログインユーザーが投稿作成者なら削除のみ実行可能。
routesの設定
resources :posts do
resources :comments, only: [:create, :edit, :update, :destroy]
end
ターミナルで確認する。
post_comments POST /posts/:post_id/comments(.:format) comments#create
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
post_comment PATCH /posts/:post_id/comments/:id(.:format) comments#update
PUT /posts/:post_id/comments/:id(.:format) comments#update
DELETE /posts/:post_id/comments/:id(.:format) comments#destroy
コントローラーの設定
@commentを追加した。
post/show.html.erbテンプレートからコメントをする際に、
/posts/:post_id/comments/:id/edit にアクセスする時に使用するcommentモデルの主idを取得するため。
def show
@post = Post.find(params[:id])
@comment = Comment.new # 追加
@comments = @post.comments
end
def edit
@post = Post.find(params[:post_id])
@comment = Comment.find(params[:id])
end
def update
@post = Post.find(params[:post_id])
@comment = Comment.find(params[:id])
if @comment.update(comment_params)
flash[:success] = "Comment updated"
redirect_to @post
else
flash[:danger] = "Comment failed"
render 'edit'
end
end
def destroy
@post = Post.find(params[:post_id])
@comment = current_user.comments.find_by(post_id: @post.id)
@comment.destroy
redirect_to post_path(params[:post_id])
end
private
def comment_params
params.require(:comment).permit(:comment_content).merge(post_id: params[:post_id])
#form tagにてpost_idパラメータを送信して、コメントへpost_idを格納するようにする必要がある。URLを作るために。
end
コメント一覧表示用にcomment_usersメソッドを作る
has_many :comments, dependent: :destroy
has_many :comment_users, through: :comments, source: :user
コメント投稿機能とeditテンプレートを同じパーシャルを適用することで、dryにする。
また、コメント一覧を作成し、
その中に、ユーザー情報パーシャル、コメント編集、削除機能パーシャルを作る。
<%# コメント機能 %>
<p class="margin-top">コメントする</p>
<%= render 'comments/comment_form' %> # edit.html.erbと共通のパーシャル
<p class="margin-top">コメント一覧</p>
<% @comments.each do |comment| %>
<div class=comments>
<%= render 'shared/user_small_info', c: comment %>
<div class="comment_content"> <%= comment.comment_content %> </div>
<%= render 'comments/comment_edit', post: @post, c: comment %>
</div>
<% end %>
コメント一覧を作る
ユーザー情報のパーシャルを作成する。
<%= link_to gravatar_for(c.user, size: 30), c.user %>
<span class="user">
<%= c.user.name %>
</span>
<span class="timestamp">
| Posted <%= time_ago_in_words(c.created_at) %> ago.
</span>
コメントを編集、削除機能のパーシャルを作成する。
・ログインユーザーがコメント作成者なら編集と削除を実行可能。
・ログインユーザーが投稿作成者なら削除のみ実行可能。
<%# comment delete or edit %>
<% if current_user?(c.user) %>
<div class="link_to">
<%= link_to "delete", post_comment_path(post, c), method: :delete, data: { confirm: "You sure?" } %>
<!--comment => comment_path-->
</div>
<div class="link_to">
<%= link_to "edit", edit_post_comment_path(post, c) %>
</div>
<%# login user が投稿者だった場合、削除のみ可能 %>
<% elsif current_user.id == post.user_id %>
<div class="link_to">
<%= link_to "delete", post_comment_path(post, c), method: :delete, data: { confirm: "You sure?" } %>
<!--comment => comment_path-->
</div>
<% end %>
コメント編集テンプレートを作成する。
<% provide(:title, "Edit Comment") %>
<% provide(:button_text, '更新') %>
<p class="margin-top">コメントする</p>
<%= render 'comment_form' %>
編集フォームのパーシャルを作成する。
・form_withにpostモデルとcommentモデルを渡すことで、/posts/:post_id/comments/:id にアクセスするためのidを取得し、updateアクションを実行する。
・form_withにpostモデルのみ渡すことで、 /posts/:post_id/comments にアクセスするためのpost_idを取得し、createアクションを実行する。
下記を参考にした。
<%= form_with(model:[@post, @comment]) do |f| %>
<%= f.text_area :comment_content %>
<%= f.hidden_field :post_id, value: @post.id %>
<%= f.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>
おまけ
ついでに、投稿編集・削除のパーシャルも載せちゃう。
<% if current_user?(post.user) %>
<!--post => post_path-->
<div class="link_to">
<%= link_to "delete", post, method: :delete, data: { confirm: "You sure?" } %>
</div>
<%# 編集機能 %>
<div class="link_to">
<%= link_to "edit", edit_post_path(post) %>
</div>
<% elsif current_user.id == post.user_id %>
<div class="link_to">
<%= link_to "delete", post, method: :delete, data: { confirm: "You sure?" } %>
</div>
<% end %>
参考文献