オブジェクト属性が変化した? shared_example : 小林研 Rails Tips (27)

はじめに

Rails Tips の 27 回目です。今日から update の request_spec を説明します。テストの雛形は以下のようになります。

  # describe "PATCH #update" do
  #   subject { -> { patch <%= singular_table_name %>_path(one), params: {<%= singular_table_name %>: attrs} } }
  #   context "owned object" do
  #     let(:one) { object }
  #     context "正しいパラメータに対して" do
  #       before { attrs["sort_order"] = 1 }
  #       it_behaves_like "レスポンスコード確認", 302
  #       it_behaves_like "オブジェクト属性が変化した?", <%= class_name %>, :sort_order, 1
  #       it_behaves_like "リダイレクト確認"
  #       it_behaves_like "Notice メッセージ確認", "XXXを更新しました。"
  #     end

  #     context "不正なパラメータに対して" do
  #       before { attrs["name"] = "" }
  #       it_behaves_like "レスポンスコード確認", 422
  #       it_behaves_like "オブジェクト属性が変化しない?", <%= class_name %>, :name
  #       it_behaves_like "Alert メッセージ確認", "XXXの更新に失敗しました。"
  #     end
  #   end

  #   context "not owned object" do
  #     let(:one) { not_mine }
  #     it_behaves_like "レスポンスコード確認", 302
  #     it_behaves_like "rootリダイレクト確認"
  #   end
  # end

オブジェクト属性が変化した?

以下は緊急連絡先 (EmergencyCall) を作成する update の正常系の spec になります。before で属性の tel を変更した上で patch が呼ばれます。レスポンスコード確認、リダイレクト確認、Notice メッセージ確認は create と同様です。今回新規で登場するのは「オブジェクト属性が変化した?」になります。属性名と実際に変化した値を渡すことで値が変更されたことを確認します。

    describe "PATCH #update" do
      subject { -> { patch emergency_call_path(one), params: {emergency_call: attrs} } }
      context "owned object" do
        let(:one) { object }
        context "正しいパラメータに対して" do
          before { attrs["tel"] = "ABC" }
          it_behaves_like "レスポンスコード確認", 302
          it_behaves_like "オブジェクト属性が変化した?", EmergencyCall, :tel, "ABC"
          it_behaves_like "リダイレクト確認"
          it_behaves_like "Notice メッセージ確認", "緊急連絡先を更新しました。"
        end

この shared_example は以下のようになります。変化する前の値を pre_value に保存しておき、値が変化したことを確認します。

shared_examples_for "オブジェクト属性が変化した?" do |klass, key, value|
  it do
    pre_value = object.send(key)
    expect { subject.call }.to change { klass.find(object.id).send(key) }.from(pre_value).to(value)
  end
end

正しく動作させるための実装

値を変更して保存したらオブジェクト属性が変わるので、このテストが通過します。

おわりに

update では値が変更になることを確認しました。明日は異常系で値が変わらないことを確認します。