このページの内容は以下のリポジトリに1日遅れで反映されます(記事執筆前に前日分をコミットしています)。
https://github.com/hkob/hkob_blog
はじめに
Rails Tips の 69 回目です。ガイドにはないのですが、コメント編集のテストと実装を追加します。
コメントを編集する
現在、comment を表示している部分テンプレートを以下のように変更します。
- 編集リンクを追加
- 選択されたコメントは form を描画
- if comment == @comment = render "articles/comments/form" - else - %i[commenter body].each do |attr| %p= t_ars Comment, attr %p= comment.send attr %p= lotfp article_path(@article, comment_id: comment.id), title: "コメントを編集"
articles#show
では新規コメントのために、 @comment
を設定していました。今回、comment_id
が指定されたときには指定されたコメントを取得し、なかった場合のみ新規コメントを作成するようにします。
def show @comments = @article.comments.order_created_at_desc @comment = objects_from_params(Comment) || @article.comments.build end
このままだと更新用の form と新規用の form の両方が表示されてしまうので、new_record でなかった場合には、Add a comment より下を表示しないようにします。
- if @comment.new_record? %h2 Add a comment: = render "articles/comments/form"
あとは実際の処理を記述するだけです。まずはテストを記述します。
describe "PATCH #update" do subject { -> { patch article_comment_path(article, object), params: {comment: attrs} } } context "正しいパラメータに対して" do before { attrs["commenter"] = "ABC" } it_behaves_like "レスポンスコード確認", 302 it_behaves_like "オブジェクト属性が変化した?", Comment, :commenter, "ABC" it_behaves_like "リダイレクト確認" it_behaves_like "Notice メッセージ確認", "コメントを更新しました。" end context "不正なパラメータに対して" do before { attrs["commenter"] = "" } it_behaves_like "レスポンスコード確認", 422 it_behaves_like "オブジェクト属性が変化しない?", Comment, :commenter it_behaves_like "Alert メッセージ確認", "コメントの更新に失敗しました。" end end
実装は以下のようになりました。昨日の create もそのまま載せておきます。どのコントローラもほぼ同じ記述になりますね。ただし、update に失敗した時、@comments
が存在しないと自分自身が表示されなくなります。失敗した場合にはコントローラであらかじめ @comments
を取得しておく必要があります。
class Articles::CommentsController < ApplicationController before_action :take_base before_action :take_one, only: %i[update] def create @comment = @article.comments.build(comment_params) if @comment.save redirect_to @article, notice: notice_message(Comment) else flash.now[:alert] = alert_message Comment render "articles/show", status: :unprocessable_entity end end def update if @comment.update(comment_params) redirect_to @article, notice: notice_message(Comment) else @comments = @article.comments.order_created_at_desc flash.now[:alert] = alert_message Comment render "articles/show", status: :unprocessable_entity end end private def take_base @article = objects_from_params Article end def take_one @comment = object_from_params_id Comment end def comment_params params.require(:comment).permit(:commenter, :body, :article_id) end end
おわりに
コメントの編集まで完了しました。明日はコメントの削除も実施します。