gakuseis コントローラの作成(2) - 不定期刊 Rails App を作る(25)

RailsApp Rails 2018年 12月 10日

(12/11 修正) 12/6 の記事と同様に gakuseis_controller から kurasus/gakuseis_controller への書き換えを行った.

gakusei_spec の記述(new と create)

  1. spec/requests/kurasus/gakusei_spec.rb を修正する. 以下のようなテストができればよい
    • 自分のクラスが選択されていなかった場合には,kurasus_path にリダイレクトする.
    • 自分のクラスが選択されている時には,text_area を表示する.
    • 学生番号と氏名を二列で記述した Excel シートから text_area に貼り付けるようにする
    • create ではタブ区切りテキストを受け付け,必要行数分だけ Gakusei を登録する.
    • テストは学生を1名登録した場合,2名登録した場合,登録できなかった場合の三種類を実施する.
  2. describe 'GET #new' do
      context 'my kurasu' do
        subject { -> { get new_kurasu_gakusei_path(kurasu) } }
        it_behaves_like :response_status_check, 200
      end
    
      context 'not my kurasu' do
        subject { -> { get new_kurasu_gakusei_path(not_mine.kurasu) } }
        it_behaves_like :response_status_check, 302
      end
    end
    
    describe 'POST #create' do
      before { @attrs = object.attributes; object.destroy }
      subject { -> { post kurasu_gakuseis_path(kurasu), params: post_params} }
    
      context '1名の登録' do
        let(:post_params) { {number_name: "2303\tabc"} }
        it_behaves_like :response_status_check, 302
        it_behaves_like :increment_object_by_create, Gakusei
        it_behaves_like :redirect_to
        it_behaves_like :flash_notice_message, '学生を一括登録しました(1名).'
      end
    
      context '2名の登録' do
        let(:post_params) { {number_name: "2304\tabc\n2305\tdef"} }
        it_behaves_like :response_status_check, 302
        it_behaves_like :change_object_count_by_create_or_destroy, Gakusei, 2
        it_behaves_like :redirect_to
        it_behaves_like :flash_notice_message, '学生を一括登録しました(2名).'
      end
    
      context '登録なし' do
        let(:post_params) { {number_name: "abc"} }
        it_behaves_like :response_status_check, 302
        it_behaves_like :not_increment_object_by_create, Gakusei
        it_behaves_like :redirect_to
        it_behaves_like :flash_alert_message, '学生が登録できません.'
      end
    end

gakusei_controller の記述(new と create)

  1. app/controllers/kurasus/gakuseis_controller.rb を記述する. create は number_name というパラメータを行ごとに分割し,行ごとに Gakusei を作成する. ただし,学生番号は数字であることを期待する.
  2. def new
      @kurasus = current_teacher.kurasus.order_name
      redirect_to kurasus_path and return if @kurasu.nil?
    end
    
    def create
      count = 0
      (params[:number_name] + "\t\n").split(/\n/).each do |line|
        number, name = line.split(/\t/)
        if number =~ /\d+/
          gakusei = @kurasu.gakuseis.create(number: number, name: name)
          count += 1
        end
      end
      message = count > 0 ? {notice: t('.notice', {count: count})} : {alert: alert_message(Gakusei)}
      redirect_to kurasu_gakuseis_path(@kurasu, edit_mode: true), message
    end

new の view を作成

  1. app/views/kurasus/gakuseis/new.html.haml を記述する. 今回の new はモデルに依存しない form となっているが,Rails 5 からは form_with を使って同じように書ける.
  2. - content_for :title do
      - @title = "#{@kurasu.try(:name)}#{t '.title'}"
    
    = form_with url: kurasu_gakuseis_path(@kurasu), local: true do |f|
      %table
        %caption= t '.description'
        %tr
          %td= f.text_area :number_name
        %tr
          %td= f.submit

locale 文字列の用意

  1. new の description と create の notice メッセージを追加した.
  2. ja:
      (中略)
      kurasus:
        gakuseis:
          (中略)
          new:
            title: 学生の一括登録
            description: Excel で A 列に学生番号,B列に氏名を並べたファイルを作成し,2列をテキストとして貼り付けてください.
          (中略)
          create:
            notice: "学生を一括登録しました(%{count}名)."

guard の結果

  1. guard の結果は以下のようになった
  2. GET #new
      my kurasu
        behaves like response_status_check
          response should be 200
      not my kurasu
        behaves like response_status_check
          response should be 302
    POST #create
      1名の登録
        behaves like response_status_check
          response should be 302
        behaves like increment_object_by_create
          should change `Gakusei.count` by 1
        behaves like redirect_to
          should redirect to "/kurasus/3181/gakuseis?edit_mode=true"
        behaves like flash_notice_message
          should eq "学生を一括登録しました(1名)."
      2名の登録
        behaves like response_status_check
          response should be 302
        behaves like change_object_count_by_create_or_destroy
          should change `Gakusei.count` by 2
        behaves like redirect_to
          should redirect to "/kurasus/3185/gakuseis?edit_mode=true"
        behaves like flash_notice_message
          should eq "学生を一括登録しました(2名)."
      登録なし
        behaves like response_status_check
          response should be 302
        behaves like not_increment_object_by_create
          should not change `Gakusei.count`
        behaves like redirect_to
          should redirect to "/kurasus/3189/gakuseis?edit_mode=true"
        behaves like flash_alert_message
          should eq "学生が登録できません."

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