LoginSignup
5
8

More than 3 years have passed since last update.

[Rails] パンくずリストで多階層のカテゴリーを表示する

Last updated at Posted at 2020-06-12

概要

ancestryで作った多階層カテゴリーを、パンくずリストに表示させます。
パンくずリストの作成にはgretelというgemを使用しました。
今回はECサイトで見られるような、商品のカテゴリーを表示するパンくずリストを作成していきます。
パンくず カテゴリ.png

前提

  • ancestryを使ってカテゴリーテーブルを作成している。
  • カテゴリー一覧ページ、カテゴリー別商品一覧ページ(各パンくずのリンク先のページ)を作成している。

今回解説するパンくずリストの構成は以下のようになります。
トップページ > カテゴリー一覧 > 親カテゴリー > 子カテゴリー > 孫カテゴリー

参考記事

多階層カテゴリーの作成にはancestryというgemを使用しています。
導入方法については以下の記事が参考になります。
https://qiita.com/Sotq_17/items/120256209993fb05ebac
https://qiita.com/pdm21/items/fe0055b3190af790f1c0

また、カテゴリー別商品一覧ページの作成については、私の過去の投稿を参考にして頂ければと思います。
https://qiita.com/Iwa_tech/items/8c396723bd9ea8e9894f

実装

導入

gemのインストール

まずはgretelをインストールします。

# Gemfile
gem 'gretel'

# ターミナル
$ bundle install

設定ファイルの生成

ターミナルに以下のように打ち込み、実行します。

$ rails generate gretel:install

すると、configディレクトリ下に、breadcrumbs.rb というファイルが自動生成されます。
このファイル内に、どのパンくずをどのページにリンクさせるかの設定を記述していくことになります。

config/breadcrumbs.rb
crumb :root do
  link "Home", root_path
end

# crumb :projects do
#   link "Projects", projects_path
# end

# crumb :project do |project|
#   link project.name, project_path(project)
#   parent :projects
# end

# crumb :project_issues do |project|
#   link "Issues", project_issues_path(project)
#   parent :project, project
# end

# crumb :issue do |issue|
#   link issue.title, issue_path(issue)
#   parent :project_issues, issue.project
# end

# If you want to split your breadcrumbs configuration over multiple files, you
# can create a folder named `config/breadcrumbs` and put your configuration
# files there. All *.rb files (e.g. `frontend.rb` or `products.rb`) in that
# folder are loaded and reloaded automatically when you change them, just like
# this file (`config/breadcrumbs.rb`).

カテゴリー一覧ページのパンくず作成

まずは簡単に実装できる、トップページ > カテゴリー一覧 の部分のパンくずからつくります。

パンくずの定義

breadcrumbs.rb ファイル内に、パンくずのリンク先を記述します。
link_toメソッドと同じ要領で、リンクに表示する文字、リンク先のパスを指定します。

config/breadcrumbs.rb
crumb :root do
  link "トップページ", root_path
end

crumb :category_index do
  link "カテゴリー一覧", categories_path
end

viewに設置

部分テンプレート作成

複数のページから呼び出せるよう、パンくずリストの部分テンプレートを作成します。
layouts/application.html に記述してもいいですが、今回はページ毎に表示の有無を分けたかったため、部分テンプレートを使うことにしました。
separator属性には、パンくず間の区切りの表示を定義できます。

_breadcrumbs.html.haml
.breadcrumbs
  = breadcrumbs separator: " › ", class: "breadcrumbs-list"

部分テンプレート呼び出し

カテゴリー一覧ページのviewにて、パンくずリストを呼び出します。
下記の1行目の記述で呼び出すパンくずを指定しています。

app/views/categories/index.html.haml
- breadcrumb :category_index
= render "breadcrumbs"

ここまでで、カテゴリー一覧ページにパンくずリストを表示することが出来たかと思います。
ちなみに、表示しているページのパンくずには自動で current というclassが付与されるため、CSSを使って以下のように表示しているページ名を強調したりも出来ます。
パンくず1.png

カテゴリー詳細ページのパンくず作成

続いて、カテゴリー別商品一覧ページ上にパンくずリストを表示させます。
以下のように、先ほど作ったパンくずの下に続けて各カテゴリーのパンくずを追加することを目指します。

トップページ > カテゴリー一覧 > 親カテゴリー > 子カテゴリー > 孫カテゴリー

パンくずの定義

親・子・孫の3つのカテゴリーに対してパンくずを設定します。
crumb の定義部分で do |変数名| とすることで、パンくず内で変数を使えるようになります。

config/breadcrumbs.rb
# 親カテゴリーのパンくず
crumb :parent_category do |category|
  category = Category.find(params[:id]).root
  link "#{category.name}", category_path(category)
  parent :category_index
end
# -----------------------------------------------------------------
# 子カテゴリーのパンくず
crumb :child_category do |category|
  category = Category.find(params[:id])
  # 表示しているページが子カテゴリーの一覧ページの場合
  if category.has_children?
    link "#{category.name}", category_path(category)
    parent :parent_category

  # 表示しているページが孫カテゴリーの一覧ページの場合
  else
    link "#{category.parent.name}", category_path(category.parent)
    parent :parent_category
  end
end
# -----------------------------------------------------------------
# 孫カテゴリーのパンくず
crumb :grandchild_category do |category|
  category = Category.find(params[:id])
  link "#{category.name}", category_path(category)
  parent :child_category
end

parent: の後には、そのパンくずの親に設定したいcrumb名を指定します。
(カテゴリー一覧ページのように、parentの指定をしなかった場合は、rootのパンくずが親となります)

子カテゴリーのパンくずだけ処理に少し工夫が必要です。
子カテゴリーのパンくずを孫カテゴリーのページから呼び出した場合と、子カテゴリーのページから呼び出した場合の2つの条件で処理を変えるようにします。

viewに設置

最後にviewでパンくずを呼び出せば完成です。
ここでの@category には、コントローラー側の記述で、詳細表示させるカテゴリーを代入しています。
@categoryがどの階層かによって、表示させるパンくずを分けます。
呼び出したパンくずに親が設定されている場合は、親のパンくずも一緒に呼び出してくれます。

app/views/categories/show.html.haml
- if @category.root?
  - breadcrumb :parent_category
- elsif @category.has_children?
  - breadcrumb :child_category
- else
  - breadcrumb :grandchild_category
= render "breadcrumbs"

以上で、カテゴリー詳細ページにパンくずリストを表示させることが出来ました。
選択したカテゴリーによって、パンくずの階層やカテゴリー名が適切に変化するか確認しましょう。
パンくず2.png

最後に

今回はancestryで作成した多階層カテゴリーを、パンくずリストに表示させる方法を解説しました。
ここまでご覧いただき、ありがとうございました。

パンくず機能作成に当たって参考にさせて頂いた記事です
https://qiita.com/you8/items/d2d37a745060b79c112f
https://qiita.com/Azure0701/items/16de34a0010eb7f05d89

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8