ElixirSchoolのNimblePublisherのレッスンをPhoenix 1.7.8対応する
導入
ElixirSchoolにはNimblePublisherの素晴らしいレッスンがあります。
しかし、現在はレッスンの通りにやってもプログラムが動きません。
レッスンの公開当時からPhoenixフレームワークのバージョンが上がったためです。
この記事では、ElixirShcoolのNimblePublisherレッスンを最新のPhoenixフレームワークで動かすために対応する箇所を紹介します。
NimblePublisherとは
NimblePulisherとは、Dashbit社[1]が開発した記事公開ライブラリです。
Dashbit社のブログシステムの大部分をカプセル化して作られました。
NimblePublisherのコードはGitHub上で公開されています。
NimblePublisherは、以下のような特徴を持ちます。
- DB不要(ファイルベース)
- 機能は必要最低限
- マークダウン対応
- コードハイライト対応
ElixirSchoolもNimblePublisherを使って記事を作成しています。
変更点
ElixirSchoolのNimblePublisherのレッスンで作られたソースコードはGitHubで公開されています。
そこのmix.lockを見ると、Phoenixのバージョンがv1.5.6だと分かります。
Phoenix v1.5.6からv1.7.8へのアップデートに必要な対応が必要です(最低限動作するための変更になります)
- ファイルやディレクトリ構造の変更、拡張子の変更
-
.eex
を.heex
に拡張子を変更- 記法も変更
-
lib/nimble_school_web/controllers/blog_html/
を作成し、index.html.heexとshow.html.heexを配置 - template/, view/ ディレクトリは不要
-
- 呼び出すモジュールや関数を変更
-
Routes
をVerifiedRoutes
に変更 -
Phoenix.HTML.Link.link/2
を、Phoenix.Component.link/1
に置き換え
-
具体的な変更
ファイルやディレクトリ構造の変更、拡張子の変更
まず、Phoenixライブラリのバージョンが上がってディレクトリ構造やファイルの配置場所が変更になります。
具体的には、lib/nimble_school_web
配下のtemplates/
ディレクトリとviews/
ディレクトリが不要になり、controllers/blog_html/
ディレクトリを追加して記事一覧と記事詳細のためのファイルを配置します。
また、ファイルの拡張子が .eex
から.heex
に変更になります。
ディレクトリ構造の差分
差分のあるディレクトリやファイルには (*)
をマークしました。
また、分かりやすくするため変更の無いディレクトリやファイルは省略しています。
【before】
lib
(前略)
├── nimble_school_web
│ ├── controllers
│ │ ├── blog_controller.ex
│ │ └── page_controller.ex
│ ├── templates(*)
│ │ ├── blog
│ │ │ ├── index.html.eex
│ │ │ └── show.html.eex
│ │ ├── layout
│ │ │ └── app.html.eex
│ │ └── page
│ │ └── index.html.eex
│ └── views(*)
│ ├── blog_view.ex
│ ├── error_helpers.ex
│ ├── error_view.ex
│ ├── layout_view.ex
│ └── page_view.ex
(後略)
【after】
lib
(前略)
├── nimble_school_web
│ ├── controllers
│ │ ├── blog_controller.ex
│ │ ├── blog_html(*)
│ │ │ ├── index.html.heex(*)
│ │ │ └── show.html.heex(*)
│ │ ├── blog_html.ex
│ │ ├── error_html.ex
│ │ ├── error_json.ex
│ │ ├── page_controller.ex
│ │ ├── page_html
│ │ │ └── home.html.heex
│ │ └── page_html.ex
(後略)
呼び出すモジュールや関数を変更
Phoenixのバージョンが上がり、aliasの設定などが変更されたため、モジュールや関数を変更します。
Routes
をVerifiedRoutes
に変更
lib/nimble_school_web/templates/blog/index.html.eex
とlib/nimble_school_web/templates/blog/show.html.eex
で使っている Routes
モジュールが呼べなくなっています。
Routes
モジュールの実態は、NimbleSchoolWeb.Router.Helpers
です。
lib/nimble_school_web.ex
にある NimbleSchoolWeb.view/0
から view_helpers/0
の中で alias NimbleSchoolWeb.Router.Helpers, as: Routes
という形でalias登録されています。
NimbleSchoolWeb.view/0
は、NimbleSchoolWeb.BlogView
から呼ばれます。
templatesのファイルはBlogViewを経由して呼ばれるため、templatesのファイル内でRoutesモジュールが呼べます。
defmodule NimbleSchoolWeb.BlogView do
use NimbleSchoolWeb, :view
end
defmodule NimbleSchoolWeb do
(略)
def view do
quote do
use Phoenix.View,
root: "lib/nimble_school_web/templates",
namespace: NimbleSchoolWeb
# Import convenience functions from controllers
import Phoenix.Controller,
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
# Include shared imports and aliases for views
unquote(view_helpers())
end
end
(略)
defp view_helpers do
quote do
# Use all HTML functionality (forms, tags, etc)
use Phoenix.HTML
# Import basic rendering functionality (render, render_layout, etc)
import Phoenix.View
import NimbleSchoolWeb.ErrorHelpers
import NimbleSchoolWeb.Gettext
alias NimbleSchoolWeb.Router.Helpers, as: Routes
end
end
(略)
end
Phoenix 1.7.8では、Phoenix.VerifiedRoutes
モジュールを使うようになっているのでこれに置き換えます。
Phoenix.VerifiedRoutes
では、sigil_p
による短縮記法が利用できるようになっています。
# before
NimbleSchoolWeb.Router.Helpers.blog_path(@conn, :show, post)
# after
~p"/blog/#{post.id}"
【before】
<h1>Listing all posts</h1>
<%= for post <- @posts do %>
<div id="<%= post.id %>" style="margin-bottom: 3rem;">
<h2>
<%= link post.title, to: Routes.blog_path(@conn, :show, post)%>
</h2>
<p>
<time><%= post.date %></time> by <%= post.author %>
</p>
<p>
Tagged as <%= Enum.join(post.tags, ", ") %>
</p>
<%= raw post.description %>
</div>
<% end %>
【after】
<h1>Listing all posts</h1>
<%= for post <- @posts do %>
<div id="{post.id}" style="margin-bottom: 3rem;">
<h2>
<.link href={~p"/blog/#{post.id}"}><%= post.title %></.link>
</h2>
<p>
<time><%= post.date %></time> by <%= post.author %>
</p>
<p>
Tagged as <%= Enum.join(post.tags, ", ") %>
</p>
<%= raw post.description %>
</div>
<% end %>
Phoenix.HTML.Link.link/2
を、Phoenix.Component.link/1
に置き換え
読み込むモジュールが変わったことでリンクの書き方が変更になっています。
具体的には、
Phoenix.HTML.Link.link/2
を呼び出す形から、
Phoenix.Component.link/1
を呼び出す形に変わっています。
【before】
<%= link post.title, to: Routes.blog_path(@conn, :show, post)%>
【after】
<.link href={~p"/blog/#{post.id}"}><%= post.title %></.link>
おわりに
ElixirSchoolのNimblePublisherのレッスンをPhoenix 1.7.8で動かす方法を紹介しました。
ElixirSchoolの記事はGitHubで公開されPRも受け付けているため、時間を見つけて修正PR投げてみようと思います。
この記事で書いたPhoenix 1.7.8対応のソースコードはこのリポジトリに載せています(コミット汚いけれど)
-
Dashbit社はElixir言語の生みの親であるJosé Valim氏が所属する会社です ↩︎
Discussion