2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Phoenixを触ってみる その8

Posted at

今回はViewの話です。

Rendering Template

今までJavaをよく業務で使ってたが、まず大きく違うのがViewの存在。
Springなんかだと、Controller -> thymeleafなどのテンプレート の2つから成り立つ。
phoenixの場合、Controller -> View + template(.eex) の3要素になる。

templateはよくある、htmlなどを動的に生成する時に使うやつだ。eexという形式で書く。
よくあるように、変数や関数の実行結果を埋め込むことが出来る。

index.eex
<div class="jumbotron">
  <h2><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h2>
  <p class="lead"><%=message()%></p>
  <p class="lead">A productive web framework that<br />does not compromise speed and maintainability.</p>
  <p><a href="<%= Routes.page_path(@conn, :index) %>">Link back to this page </a></p>
</div>

(eexはハイライト効かないのか・・・)

Viewはexコードだ。
ここで定義した関数は、そのままtemplate上で利用可能となる。

PageView.ex
defmodule HelloWeb.PageView do
  use HelloWeb, :view
  alias HelloWeb.Router.Helpers ,as: Routes

  def message do
    "Hello from the view"
  end
end

これが、良い。
Webの処理って、リクエストを受けて処理する部分 と 画面表示用の処理をする部分 があると思うのだが
この表示用の方の立ち位置が曖昧だったと思うのだ。
表示用の処理だから表示側に寄せたいが、テンプレートで複雑なロジックは可読性を下げるし、そもそもロジックを書くのに向いていない。
昨今のSPAのような形も一つの解だと思うが、
サーバ側の処理を明確に分けることが出来るのは、とても嬉しい。

あと以下の様な特徴がある。

  • Controllerとの対応は、命名で決まってる
    • PageControllerならば、PageViewとtemplates/page/ ディレクトリ
  • templateは、phoenixによってプリコンパイルされてViewの関数として組み込まれる
    • だからView上の関数はそのまま使えるし、aliasなんかもViewに追加すればtemplateで使える
    • render("index.html", _assign) のような形
      • 先にView上で定義しておけば、index.html.eexレンダリングの代わりに実行される
    • サーバ起動時点でメモリに乗ってる。リクエスト毎にファイルを読んでるわけではない
      • 代わりに、テンプレート変更時でも再コンパイルが必要

More About Views

  • .eexで変数の表示は "@"を使う
  • htmlエスケープも勝手にされる
  • layoutっていう外枠表示してるものも同じ仕組み(View + template)
    • templates/layout/app.html.eex見ると、中でrender/3を呼んでる
    • つまり、ふつーに.eex内でrenderすれば、画面パーツをView込で呼べる・・・!

この最後のやつ。画面をパーツ化する時に、template以外はなんのパーツを使うか知らなくて良くなるね。

結構phoenix自体の作りに踏み込んだ説明もしてくれているので、原文読んでください。

The ErrorView

  • エラーもErrorViewが使われて、templates/error/にeex置けば良い
  • ステータスコード + .html.eex で呼ばれる
    • 404.html.eex みたいな
  • とはいえ、ErrorViewでエラーになると良くないので、程々に
    • 手元でやった感じ、空っぽの500が返った

Rendering JSON

json返すだけならViewやtemplate無しでもいける
けど、返却用にデータを加工するところはControllerとは分けたほうが良いよね、という内容。

Viewで複数render作れば、良い感じに階層構造が作れるので、うまく使ってね、ということらしい。

PageView.ex
  def render("index.json", %{pages: pages}) do
    %{data: render_many(pages, HelloWeb.PageView, "page.json")}
  end

  def render("show.json", %{page: page}) do
    %{data: render_one(page, HelloWeb.PageView, "page.json")}
  end

  def render("page.json", %{page: page}) do
    %{title: page.title}
  end

この例では、以下を返すことになる。

  • index.jsonの中身は複数のpage情報
  • show.jsonでは単一のpage情報

以上Viewでした。
今までのフレームワークで不満だった点が良い感じに解消されていそうで良い感じ。
かつ、一つ一つのパーツもシンプルにできているようで、とても勉強になります。

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?