Nao000のぶろぐ

蝶を追っている少年になりたい

【Elixir Phoenix】パンくずリストを自前で実装する

目次

  1. バージョン情報
  2. すでにモジュールはないのか
  3. どこに実装するか
  4. コード
  5. 所感
  6. 参考サイト

バージョン情報

Elixir: 1.8.1

Phoenix: 1.4.2

すでにモジュールはないのか

breadcrumble_exというモジュールでパンくずリストを生成できそうです。

最初は「このぐらいなら自分で作ればいいかな」と思ったのですが、普通にこちらを使えばいいと思います。けど、自前で作ってしまったので記事にします。良い子は自作しないでね。

どこに実装するか

どこに実装するか非常に迷いましたが、各コントローラーとViewに実装することにしました。共通モジュールを用意しようと考えましたが、パンくずリストは各画面の役割と判断しました。

コード

概要的には、Controller => template => View の流れです

Controller

/category/elixir/ にアクセスした際に実行される関数内でマップを要素にもつパンくずリストを用意します。

        pankuzu = [
          %{name: "TOP", url: "/"},
          %{name: "カテゴリ一覧", url: "/category/"},
          %{name: category.name <> "カテゴリ一覧", url: nil}
        ]

template

画面の共通部分である app.html.eex に出力します。pankuzu関数がパンくずリスト生成関数です。エスケープされたくないので raw関数 も使っています。

      <body>
        <header class="blogInfo">
          <h1 class="title"><a href="/" class="anchor">Nao000のぶろぐ</a></h1>
          <h2 class="summary">蝶を追っている少年になりたい</h2>
        </header>
        <%= raw pankuzu(@conn) %>
        ...

View

layout_view.ex に出力用関数を用意します。

    defmodule Nao000dotcomWeb.LayoutView do
      use Nao000dotcomWeb, :view
      ...

      def pankuzu(conn) do
        pankuzuDom(conn.assigns[:pankuzu])
      end

      defp pankuzuDom(nil) do
        ""
      end

      defp pankuzuDom(pankuzu) do
        pankuzuList =
          Enum.map(pankuzu, fn item ->
            if item.url == nil do
              "<li class="item">" <> item.name <> "</li>"
            else
              "<li class="item"><a href="#{item.url}">" <> item.name <> "</a></li>"
            end
          end)

        "<nav><ul class="breadcrumb">" <> Enum.join(pankuzuList) <> "</ul></nav>"
      end
    end

所感

ベストプラクティスな実装は分かりません。コスト的に考えると最初に紹介したモジュールを使うことがベストだと思います。現在の実装で問題が生じたら、このモジュールにリファクタすればいいかなと思っています。

参考サイト