はじめに
Rails Tips の 37 回目です。今回は、ページの上に記載するパンくずリストを描画する url_navi ヘルパーです。
該当する application.html.haml
パンくずリストを各ページの先頭に記述してしまうと、notice
や alert
などの下にパンくずリストが展開されてしまいます。そこで、パンくずリストの内容は各ページの :navi
に相当する content_for
の中に記載します。この部分は、以前ページタイトルを取得した時と同様に application.html.haml
の中で yield
によって呼び出します。もし、content_for
が存在した時に、その yield
の返り値を #navi id
の下に展開します。
%body - cc = controller.class - finished = cc.finished?(action_name) = render "shared/top_link_bar", navi: @navi - if content_for?(:navi) #navi= yield :navi #notice{class: notice ? "notice" : ""}= notice #alert{class: alert ? "alert" : ""}= alert
各ページのトップには、以下のようにして今回解説する url_navi ヘルパーにパンくずリストの掲載するパスを配列で渡します。
- content_for :navi do - url_navi [teacher_jikanwaris_path, teacher_kurasu_shikens_path(@kurasu)]
url_navi の中身
excel や word での出力でない時(html出力の時)に shared/navi_link_bar を描画した結果を返します。
# @param [Array<String, Array<String>>] array 「リンク文字列とパスの配列」または「パス」のどちらかを要素に持つ配列 # @return [String] レンダリング結果 def url_navi(array) render "shared/navi_link_bar", navi_data: array unless @excel_page || @word_page end
shared/_navi_link_bar.html.haml の中身
navi_link_bar の中身はこんな感じです。今回説明するつもりのない権限周りもそのまま掲載しておきます。現在のページを示すパスの最後だけは単に文字列が表示され、それ以前のものはリンクになります。リンクの文字列は基本的には locales から取得しますが、例外的に文字列も一緒に渡すとそちらを利用するようにしています。校務支援システムでは、パスからページ閲覧および編集権限が取得できるようにしているのでその辺りも描画されています。
:ruby navi_data ||= [] %ul - last = navi_data.last - navi_data.each_with_index do |path_or_array, i| %li= ">" unless i == 0 - if path_or_array.is_a? Array - value, path = path_or_array - cap = controller_action_and_params(path) - else - path = path_or_array - cap = controller_action_and_params(path) - value = title_from_cap cap %li - if path_or_array == last = value - ps = privileges_str_from_cap cap - eps = @edit_privileges ? privileges_str(@edit_privileges) : nil - if eps && eps != ps = "(権限: #{ps}、編集権限: #{eps})" - elsif ps = "(権限: #{ps})" - else = link_to_lh value, path
おわりに
ページの先頭に url_navi
ヘルパーを含んだ content_for
を記述するだけで、各ページにパンくずリストを描画することができます。url_navi の引数は単にパスを記述するだけなので、非常に簡単です。仕組みは結構面倒くさいですが、一度作り込んでしまえば、毎回記述する部分はかなり短くなるのは Rails のいいところかなと思います。