25. パンくずリストへの権限の描画

現在のシステムで各ページが誰に見えているのかがわからないという問い合わせが多かった。今回は、コントローラに定数を記述し、それを確認することで権限を一元管理することにしている。前回、せっかくパンくずリストを表示したので、この部分に権限を表示することにした。

navi_link_bar の修正

前回

  = navi [ @title ]

と書いてもよいことにしたが、こちらは通常通り

  = navi [ nil, teacher_kyoumus_path ]

と書くことにする。これをうけて、app/views/shared/_navi_link_bar.html.haml の該当部は以下のように修正した。パンくずの最後の場合、privileges_str_from_path で取得した権限一覧を () 付で表示する。

    %li
      - if path == last
        = value || title_from_path(path)
        - ps = privileges_str_from_path(path)
        = "(#{ps})" if ps

privileges_str の実装

privileges_str_from_path は helper に記載するが、まず先に spec/helpers/application_helper_spec.rb に記載する(そういえばここまで helper のテストをしてなかった)。

  it 'should obtain privileges array from path' do
    expect(privileges_from teacher_kyoumus_path).to eq %w( is_kyoumu? )
  end

  it 'should obtain privileges string from privileges array' do
    expect(privileges_str %w( is_kyoumu? )).to eq "教務室"
  end

  it 'should obtain privileges string from path' do
    expect(privileges_str_from teacher_kyoumus_path).to eq "教務室"
  end

これを満たす実装を app/helpers/application_helper.rb に記述する。

  # @param [String] path URL
  # @return [String] 権限の文字列
  def privileges_str_from_path(path)
    privileges_str(privileges_from(path))
  end

  # @param [String] path URL
  # @return [Array<String>] 権限の配列
  def privileges_from_path(path)
    path = Rails.application.routes.recognize_path(path)
    ca, a = path.values_at(:controller, :action)
    privileges = "#{ca}_controller".classify.constantize::Privileges
    privileges[a.to_sym] if privileges
  end

  # @param [Array<String>] 権限の配列
  # @return [String] 権限の文字列
  def privileges_str(privileges)
    privileges.map { |p| I18n.t "privilege.#{p}" }.join('') if privileges
  end

privilege.権限シンボルという文字列が取得できるので、これに対応する locale を config/locales/views/privileges/ja.yml に設定する。

ja:
  privilege:
    is_kyoumu?: 教務室
    is_staff?: 教職員
    is_staff?: 教職員
    is_gakusei?: 学生室
    (以下省略)

これで権限がパンくずリストの最後に () 付で権限が表示された。

spec/helpers/application_helper_spec.rb の追記

page_title を使わないようにしたので、title_from_path も app/controllers/application_controller.rb から helper に移した。他にも、app/helpers/application_helper.rb にいろいろとメソッドを追加していたが、受入テストで間接的にテストをしているだけだったので、真面目に spec/helpers/application_helper_spec.rb にいろいろと記述した。

リンク用のヘッダを表示するヘルパ。第二引数も追加し、false の時には [] を付けないように変更した(次回この変更が必要となる)。

  it 'should obtain link string' do
    expect(lh('abc')).to eq '[abc]'
    expect(lh('abc', true)).to eq '[abc]'
    expect(lh('abc', false)).to eq 'abc'
  end

ActiveRecord の翻訳用メソッド ‘model名.属性’ で属性の翻訳文字列を得る。属性ではないものも翻訳リストに載せれば表示できる。model 名のみであればモデル名の翻訳文字列を得る。

  it 'should obtain localized strings' do
    expect(t_ar 'Year').to eq '年度'
    expect(t_ar 'Year.year').to eq '西暦'
  end

以前、class_info_or_nil というメソッドを書いたが Bootstrap でいろいろと class を設定することが多くなりそうなので、汎用的な class_str_or_nil に変更した。info が一番増えそうなので、デフォルト値を :info にする。

  it 'should obtain str class when flag is true' do
    expect(class_str_or_nil(true)).to eq({ class: 'info' })
    expect(class_str_or_nil(false)).to eq({})
    expect(class_str_or_nil(true, 'active')).to eq({ class: 'active' })
    expect(class_str_or_nil(false, 'active')).to eq({})
  end

○×を得る

  it 'should obtain ○ or × from flag' do
    expect(mb true).to eq ''
    expect(mb false).to eq '×'
  end

application_controller.rb から移動した path から title を取得するメソッド。

  it 'title_from_path should obtain title from path' do
    expect(title_from_path(teacher_kyoumus_path)).to eq '教務室トップページ'
  end

今日はここまで。