はじめに
Rails Tips の 40 回目です。リンクは lotfp
で簡単に書くことができましたが、メニューページのリンクはリンクだけでなく、説明文や権限の表示なども同時に表示します。これもたくさん記述するのでメニューページの描画を簡単にする write_menu
ヘルパーを作成しています。
write_menu の使い方
基本的にはこんな感じでメニューを作成しています。通常はパス名を記述するだけです。
%h2 行事日程関係 %table.bordered = menu_link_title %tbody = write_menu teacher_events_path
lotfp
と同様に locales に登録しているものと異なるリンクタイトルにしたい場合には title
を指定します。ここでは「(今年度)」という情報を追加したいため title
を別途指定しています。
= write_menu list_teacher_syllabus_pages_path(edit_year_id: @now_year.id), title: "最近更新したシラバス(今年度)"
通常は edit action の権限を編集権限で確認しますが、edit action が存在しないコントローラの場合には、edit_action
で権限確認する action を指定します。
= write_menu shussekibo_teacher_lectures_path(date: Time.zone.today), edit_action: :create
共通メニューなどは全員に権限があるため、わざわざ権限描画はしません。この場合 no_priv
を設定すると権限列を描画しません。
= write_menu teacher_jikanwaris_path, no_priv: true
分類用に1列目に rowspan を追加したいときには、add_rowspan
を追記します。
= write_menu teacher_kenshins_path, add_rowspan: ["保健室関連", 2]
menu_link_title の実装
write_menu の前に記述してあった menu_link_title を先に紹介します。基本は、リンク、内容、権限のヘッダを描画するだけです。add_type
を true した場合、1列目に分類が追加され、no_priv
を true にした場合、権限列がなくなります。
# @param [Boolean] add_type 分類を追加する時に true # @param [Boolean] no_priv 権限を追加しない時に true # @return [ActiveSupport::SafeBuffer] メニューリンクタイトル def menu_link_title(add_type: false, no_priv: false) headers = (add_type ? %w[分類] : []) + %w[リンク 内容] + (no_priv ? [] : %w[権限]) content_tag :thead do content_tag :tr do headers.each do |w| concat(content_tag :th, w) end end end end
write_menu_sub の実装
write_menu
はパスからリンクの説明と権限を描画します。それらを取得するサブメソッドである write_menu_sub
を作っておきます。write_menu_sub はこれまで紹介してきた detail_from_cap などを呼び出して配列を準備するだけのものです。
# @param [Hash] session user_session または admin_session # @param [String] path URL # @param [Symbol, nil] method GET 以外の場合は記述 # @return [Array<String>] 表示するメニュー要素の配列 def write_menu_sub(path, method = :get, edit_action: :edit) cap = controller_action_and_params(path, method) normal = privileges_str_from_cap(cap) edit = privileges_str_from_cap cap.merge({action: edit_action}) [ detail_from_cap(cap), (edit.blank? || normal == edit) ? normal : "#{normal} (編集: #{edit})", ] end
write_menu の実装
write_menu
は write_menu_sub
で取得した情報を使って、content_tag ヘルパーでメニューを作成しています。Rails 5 からは content_tag の代わりに tag ヘルパーを使うことが推奨されているのですが、tag.tr と記述すると RubyMine のエラー(String.tr と混同して引数が足りないとエラーになる)が消えなくなってしまうので、いまだに content_tag を使っています。
# @param [Hash] session user_session または admin_session # @param [String] path URL # @param [Symbol, nil] method GET 以外の場合は記述 # @return [String] 表示するメニュー行 def write_menu(path, method = :get, add_rowspan: nil, title: nil, detail: nil, edit_action: :edit, cond: true, no_priv: false) auto_detail, privileges = write_menu_sub(path, method, edit_action: edit_action) detail ||= auto_detail content_tag :tr do concat(content_tag :th, add_rowspan.first, rowspan: add_rowspan.last) if add_rowspan concat content_tag :th, lotfp(path, method, title: title, cond: cond), class: "left" concat content_tag :td, detail, class: "left" concat(content_tag :td, privileges, class: "left") unless no_priv end end
おわりに
これまでメニューを一つ表示するだけでも haml で5行くらいの手書きをしていたのですが、write_menu だとリンクをひとつ書くだけになりました。おかげでメニューページはかなりスッキリしました。