💡
この記事は Middleman 時代に書いた古いものです。記録のため、astro-notion-blog に移行していますが、あまり参考にしないでください。
events/event_gakuseis のコントローラは index と update のみとなる. このコントローラでは,AJAX での画面遷移を意識して,id を配置している.
event_gakuseis コントローラの追加
-
generator で events/event_gakuseis コントローラを作成する.
$ bin/rails g controller events/event_gakuseis Running via Spring preloader in process 30317 create app/controllers/events/event_gakuseis_controller.rb invoke haml create app/views/events/event_gakuseis invoke rspec invoke assets invoke js invoke css
-
generator で integration_test を作成する. 前と同様に,event_gakuseis で spec を作成後にフォルダを移動することにする.
$ bin/rails g integration_test event_gakusei Running via Spring preloader in process 30351 invoke rspec create spec/requests/event_gakuseis_spec.rb
-
event_gakuseis_spec.rb を spec/requests/events の下に移動する.
mkdir -p spec/requests/events; mv spec/requests/event_gakuseis_spec.rb spec/requests/events
-
routes に events/event_gakuseis の項目を追加する.
Rails.application.routes.draw do (中略) resources :events, only: [] do resources :event_gakuseis, only: %i[index update], controller: 'events/event_gakuseis' end
event_gakuseis_spec の記述(index のみ)
-
spec/requests/events/event_gakuseis_spec.rb を修正する. ひな形からほぼ自動で作成されるので,index 以外の場所を if false で実行しないようにしておく.
require 'rails_helper' RSpec.describe :EventGakuseis, type: :request do include Devise::Test::IntegrationHelpers let(:object) { event_gakusei_factory :start_foo } let!(:gakuseis) { gakusei_factories %i[foo2301 bar2302] } let(:not_mine) { event_gakusei_factory :hr_baz3301 } let!(:event) { event_factory :start2300_0406 } let(:return_path) { event_event_gakuseis_path(edit_mode: true) } context 'login by hkob' do teacher_login :hkob describe 'GET #index' do context 'owned event' do subject { -> { get event_event_gakuseis_path(event) } } it_behaves_like :response_status_check, 200 it_behaves_like :response_body_includes, %w[始業 2301 foo] end context 'not owned event' do subject { -> { get event_event_gakuseis_path(not_mine.event) } } let(:return_path) { kurasus_path } it_behaves_like :response_status_check, 302 it_behaves_like :response_body_not_includes, %w[始業 2301 foo] it_behaves_like :flash_alert_message, 'イベントを表示する権限がありません.' end end if false (中略) end end context 'not login' do describe 'GET #index' do subject { -> { get event_event_gakuseis_path(event) } } it_behaves_like :response_status_check, 302 it_behaves_like :response_body_not_includes, %w[始業 2301 foo] end end end
events/event_gakuseis_controller の記述(index のみ)
-
app/controllers/events/event_gakuseis_controller.rb を記述する. 最初の表示の時のみ,@kurasu.gakuseis から event_gakuseis を自動生成するようにしている.
class Events::EventGakuseisController < ApplicationController before_action :authenticate_teacher! before_action :get_event def index redirect_to(kurasus_path, alert: t('.not_my_event')) and return if @event.nil? @kesseki_mode = true if params[:kesseki_mode] @event_gakuseis = @event.event_gakuseis.order_number if @event_gakuseis.count == 0 @event_gakuseis = [] @kurasu = @event.kurasu @kurasu.gakuseis.order_number.each do |g| @event_gakuseis << @event.event_gakuseis.create(gakusei_id: g.id, shusseki: EventGakusei.shussekis[:unsettled]) if g.event_gakuseis.event_is(@event).count == 0 end end end def get_event @event = Event.find_by_id(params[:event_id]) @event = nil if @event && @event.kurasu.teacher != current_teacher end private :get_event end
-
event_gakusei で event をフィルタする event_is という scope を用意する.
scope :event_is, -> e { where arel_table[:event_id].eq e.id }
index の view を作成
-
app/views/events/event_gakuseis/index.html.haml を記述する. 未設定,出席,欠席のそれぞれで学生ごとにIDを設定し,その内部は partial で描画を行う.
- content_for :title do - @title = "#{t '.title'}: #{@event.name}, #{@event.kurasu.name}" .row - EventGakusei.shussekis.each do |key_array| - key = key_array.first .column{class: key} - key_title = t_ar EventGakusei, "shusseki.#{key}" - mode = key_array.last - case mode - when 0 .button.button-outline= key_title - when 1 - if @kesseki_mode = link_to key_title, event_event_gakuseis_path(@event), class: 'button button-outline' - else .button= key_title - when 2 - if @kesseki_mode .button= key_title - else = link_to key_title, event_event_gakuseis_path(@event, kesseki_mode: true), class: 'button button-outline' %br - @event_gakuseis.each do |eg| - g = eg.gakusei %div{id: "#{g.id}_#{mode}"} = render partial: 'index_sub.html', locals: {event_gakusei: eg, kesseki_mode: @kesseki_mode, mode: mode}
-
partial の中身はデータが存在するときに,link_to を描画する. link_to のリンク先は,未設定の場合には kesseki_mode の値にしたがって,出席・欠席へのリンクを設定し,出席・欠席の場合には未設定へのリンクを設定する.
- event = event_gakusei.event - gakusei = event_gakusei.gakusei - if event_gakusei.shusseki_before_type_cast == mode = link_to gakusei.number_name, event_event_gakusei_path(event, event_gakusei, event_gakusei: {shusseki: mode == 0 ? kesseki_mode ? :kesseki : :shusseki : :unsettled}, kesseki_mode: kesseki_mode), class: :button, method: :put, remote: true
-
app/models/gakusei.rb に number_name というコンビニエンスメソッドを追加しておいた.
# @return [String] 学生番号と氏名を返す def number_name "#{number} #{name}" end
locale 文字列の用意
-
model の locale はいつものように config/locales/models.ja.yml に追加しておく. 今回は,event_gakusei に enum を追加しているため,event_gakuse/shusseki として文字列を追加している. こうすることで,t_ar EventGakusei, 'shusseki.unsettled' のように enum の翻訳文字列へアクセスできる.
ja: activerecord: models: event_gakusei: イベント学生 (中略) attributes: event_gakusei: shusseki: 出席 event_gakusei/shusseki: unsettled: 未設定 shusseki: 出席 kesseki: 欠席
-
view には locale 用のキーワードしか書いていないので,それらの文字列を config/locales/views.ja.yml に追加しておく.
ja: events: event_gakuseis: index: title: 出席簿 not_my_event: イベントを表示する権限がありません.
guard の結果
-
guard の結果は以下のようになった
EventGakuseis login by hkob GET #index owned event behaves like response_status_check response should be 200 behaves like response_body_includes response body includes ["始業", "2301", "foo"] not owned event behaves like response_status_check response should be 302 behaves like response_body_not_includes response body does not include ["始業", "2301", "foo"] behaves like flash_alert_message should eq "イベントを表示する権限がありません." not login GET #index behaves like response_status_check response should be 302 behaves like response_body_not_includes response body does not include ["始業", "2301", "foo"]
長くなったので今日はここまで