kurasus_controller の request spec(2) - 不定期刊 Rails App を作る(17)

RailsApp Rails RSpec 2018年 11月 27日

request spec による new のテストと実装

  1. GET #new の spec を spec/requests/kurasus_spec.rb に記載する.new はレスポンスが 200 であることを確認できればよい.
  2. describe 'GET #new' do
      subject { -> { get new_kurasu_path } }
      it_behaves_like :response_status_check, 200
    end
  3. GET #new の実装を app/controllers/kurasus_controller.rb に記載する.
  4. def new
      @kurasu = current_teacher.kurasus.build(name: 'クラス名', obsolete: false)
    end
  5. GET #new のビューを app/views/kurasus/new.html.haml に記載する. ここはタイトルの設定と _form の読み込みのみである.
  6. - content_for :title do
      - @title = "#{t '.title'}: #{current_teacher.name}"
    = render partial: 'form', locals: {kurasu: @kurasu}
  7. 読み込まれる _form.html.haml は Rails 5.1 から導入された form_with を使う. これは new だけでなく edit からも読み込まれる. new の場合は,obsolete = false のものを作成するため,入力欄は表示せず hidden_field で渡す. html 5 からは autofocus は Javascript を使わずに設定できるようになっている.
  8. - is_edit = controller.action_name == 'edit'
    = form_with model: kurasu, local: true do |f|
      %table
        %tr
          %th= f.label :name
          %td= f.text_field :name, autofocus: true
        - if is_edit
          %tr
            %th= f.label :obsolete
            %td= f.check_box :obsolete, {checked: kurasu.obsolete}, 'true', 'false'
        %tr
          %td{colspan: 2}
            - unless is_edit
              = f.hidden_field :obsolete
            = f.hidden_field :teacher_id
            = f.submit

request spec による create のテストと実装

  1. POST #create の spec を spec/requests/kurasus_spec.rb に記載する.追加に成功する場合と失敗する場合の二種類を確認できればよい. 利用した shared_example は以下の通りである.
    • increment_object_by_create: モデルが一つ追加されるか確認
    • flash_notice_message: notice メッセージが設定されているか確認
    • redirect_to: return_path にリダイレクトされるか確認
    • not_increment_object_by_create: モデルが追加されないことを確認
    • flash_alert_message: alert メッセージが設定されているか確認
  2. describe 'POST #create' do
      before { @attrs = object.attributes; object.destroy }
      subject { -> { post kurasus_path(edit_mode: true), params: {kurasu: @attrs}} }
    
      context '正しいパラメータに対して' do
        it_behaves_like :response_status_check, 302
        it_behaves_like :increment_object_by_create, Kurasu
        it_behaves_like :flash_notice_message, 'クラスを登録しました.'
        it_behaves_like :redirect_to
      end
    
      describe '不正なパラメータに対して' do
        before { @attrs['name'] = nil }
        it_behaves_like :response_status_check, 200
        it_behaves_like :not_increment_object_by_create, Kurasu
        it_behaves_like :flash_alert_message, 'クラスが登録できません.'
      end
    end
  3. POST #create の実装を app/controllers/kurasus_controller.rb に記載する. kurasu_params というメソッドにより params の属性のフィルタリングを行なっている(permit しない属性は無視される). また,notice_message, alert_message は DRY にするためにメソッド化している.
  4. def create
      @kurasu = Kurasu.new(kurasu_params)
      if @kurasu.save
        redirect_to kurasus_path(edit_mode: true), notice: notice_message(Kurasu)
      else
        flash.now[:alert] = alert_message(Kurasu)
        render action: :new
      end
    end
    
    def kurasu_params
      params.require(:kurasu).permit(:teacher_id, :name, :obsolete)
    end
    private :kurasu_params
  5. notice_message, alert_message は app/controllers/application_controller.rb に記載する. それぞれ,flash.create.notice, flash.create.alert から locale を取得するようになっている. また,update の時にも使えるように,create の部分は action_name から作成している.
  6. def notice_message(klass)
      I18n.t "flash.#{action_name}.notice", {obj: klass.model_name.human}
    end
    
    def alert_message(klass)
      I18n.t "flash.#{action_name}.alert", {obj: klass.model_name.human}
    end
  7. flash.{create, update}.{notice, alert} の locale を config/locales/views.ja.yml に追加しておく. また,次回作成する edit, update などの locale も一緒に作成しておく. locale にはこんな感じで引数が指定できる.
  8. ja:
      flash:
        create:
          notice: "%{obj}を登録しました."
          alert: "%{obj}が登録できません."
        update:
          notice: "%{obj}を更新しました."
          alert: "%{obj}が更新できません."
        edit:
          alert: "%{obj}を編集する権限がありません."
        destroy:
          notice: "%{obj}を削除しました."
          alert: "%{obj}を削除する権限がありません."
        show:
          alert: "%{obj}を表示する権限がありません."
  9. 最終的な guard 出力はこんな感じになった(本日分のみ).全てテストが通過している.
  10. GET #new
      behaves like response_status_check
        response should be 200
    POST #create
      正しいパラメータに対して
        behaves like response_status_check
          response should be 302
        behaves like increment_object_by_create
          should change `Kurasu.count` by 1
        behaves like redirect_to
          should redirect to "/kurasus?edit_mode=true"
        behaves like flash_notice_message
          should eq "クラスを登録しました."
      不正なパラメータに対して
        behaves like response_status_check
          response should be 200
        behaves like not_increment_object_by_create
          should not change `Kurasu.count`
        behaves like flash_alert_message
          should eq "クラスが登録できません."

長くなったので今日はここまで