このページの内容は以下のリポジトリに1日遅れで反映されます(記事執筆前に前日分をコミットしています)。
https://github.com/hkob/hkob_blog
はじめに
Rails Tips の 68 回目です。昨日の続きでコメント追加のテストと実装を追加します。
8.4 コントローラを生成する(テストと実装)
昨日作成した submit ボタンを押した時の create アクションをテストします。
require "rails_helper" RSpec.describe Articles::CommentsController, type: :request do let!(:comment) { comments :can_delete } let!(:object) { comment } let!(:article) { object.article } let!(:attrs) { object.attributes } # let(:not_mine) { comments :not_mine } let(:return_path) { article_path(article) } (中略) describe "POST #create" do before { object.destroy } subject { -> { post article_comments_path(article), params: {comment: attrs} } } context "正しいパラメータに対して" do it_behaves_like "レスポンスコード確認", 302 it_behaves_like "オブジェクトが1増えるか?", Comment it_behaves_like "リダイレクト確認" it_behaves_like "Notice メッセージ確認", "コメントを登録しました。" end context "不正なパラメータに対して" do before { attrs["commenter"] = "" } it_behaves_like "レスポンスコード確認", 422 it_behaves_like "オブジェクト数が変化しない?", Comment it_behaves_like "Alert メッセージ確認", "コメントの登録に失敗しました。" end end
articles/comments_controller.rb
は以下のようになります。このコントローラでは、すべてのアクションで @article
を取得する必要があるので、 take_base
というメソッドを before_action
で呼び出すようにしています。ここで使われている objects_from_params
はここで説明しています。
class Articles::CommentsController < ApplicationController before_action :take_base 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 private def take_base @article = objects_from_params Article end def comment_params params.require(:comment).permit(:commenter, :body, :article_id) end end
また、前回の article の時に追加すべきでしたが、notice や alert のメッセージを表示する場所を用意していませんでした。 application.html.haml
の先頭に id をつけて登録しておきます。後で適切な CSS を設定するとよいと思います。
%body #notice= notice #alert= alert - if @page_title.present? %h1= @page_title = yield
ここで commenter や body を空に設定したりすると、label の部分にエラーができるようになっています。それらを正しく入力するとコメントが追加されることがわかります。
おわりに
コメントの追加ができたので、明日はガイドでは実施していないコメントの編集や削除を実装してみましょう。