はじめに
Rails Tips の 29 回目です。今日は destroy の request_spec を説明します。テストの雛形は以下のようになります。
# describe "DELETE #destroy" do # subject { -> { delete <%= singular_table_name %>_path(one) } } # context "owned object" do # let(:one) { <%= singular_table_name %> } # it_behaves_like "レスポンスコード確認", 302 # it_behaves_like "オブジェクトが1減るか?", <%= class_name %> # it_behaves_like "リダイレクト確認" # it_behaves_like "Notice メッセージ確認", "XXXを削除しました。" # end # context "now owned object" do # let(:one) { not_mine } # it_behaves_like "レスポンスコード確認", 302 # it_behaves_like "rootリダイレクト確認" # end # end
オブジェクト属性が変化しない?
以下は昨日の緊急連絡先 (EmergencyCall) の destroy の spec になります。権限のある emergency_call と 権限のない not_mine で one の let を切り替えることで両方のテストをしています。権限がある方は、303 (See other) のレスポンスコードを返し、リダイレクト確認および Notice メッセージを確認します。レスポンスコードを 303 に設定しないと、Turbo の場合別のオブジェクトが削除されてしまうので注意が必要です。destroy の場合、オブジェクトが一つ減るため、今回の「オブジェクトが1減るか?」を呼び出します。
describe "DELETE #destroy" do subject { -> { delete emergency_call_path(one) } } context "owned object" do let(:one) { emergency_call } it_behaves_like "レスポンスコード確認", 303 it_behaves_like "オブジェクトが1減るか?", EmergencyCall it_behaves_like "リダイレクト確認" it_behaves_like "Notice メッセージ確認", "緊急連絡先を削除しました。" end context "now owned object" do let(:one) { not_mine } it_behaves_like "レスポンスコード確認", 302 it_behaves_like "rootリダイレクト確認" end end
この shared_example は以下のようになります。オブジェクトが1増えるかの反対に一つ減ることを確認するだけです。
shared_examples_for "オブジェクトが1減るか?" do |klass| it "#{klass}.count が 1 つ減ること" do expect { subject.call }.to change(klass, :count).by(-1) end end
正しく動作させるための実装
権限の確認を行い、自分のオブジェクトでなければ welcome_path にリダイレクトします。権限がある場合にはオブジェクトを削除し、see_other ステータスでリダイレクトします。
def destroy# @emergency_call, @ids = get_parameters_and_ids [EmergencyCall.gp(true)] @gakusei = @emergency_call.gakusei @gnumber = @gakusei.gnumber_year_is(@now_year) redirect_to welcomes_path_with_message and return unless my_gnumber?(@gnumber) || pr_kyoumu? || charged_gnumber? @emergency_call.destroy redirect_to gakusei_path(@gakusei), notice: notice_message(EmergencyCall), status: :see_other end
おわりに
これで一通り request spec で使っている shared example を全て紹介しました。次回からは普段使っている helper_method を中心に紹介していきます。