スポンサーリンク

2015年6月3日

Phoenixのビュー(Views)について分かったこと

タイトル: Phoenixのビュー(Views)について分かったこと

目的: Phoenixアプリケーションのビュー(Views)について分かったことを記述する。

実施環境:
OS: Windows8.1
Erlang: Eshell V6.4
Elixir: v1.0.4
Phoenix Framework: v0.13.1
Node.js: v0.12.4

目次:

  1. 概要
  2. Viewsの基本的なこと
  3. Viewsについてもっと
  4. レイアウトについて簡単に
  5. ErrorViewについて

1.概要

1.1
今日は、Viewsに関してです。

注意!!
この記事は、Phoenix - Guides ViewsをGoogle翻訳の力を借り、
素人翻訳して分かったことを書いています。

原文を丸々翻訳しているわけではないので、
流れや説明がおかしいところ多々ありますが、その点注意して下さい。
英語が分かる方は、公式を見た方が確実です。

また、管理人の英語力は本人がドン引きするほど低いので、
間違った解釈及び理解している部分が多分にあると思います。

それでも構わないという方は見て頂けたら嬉しいです。

また、ご指摘等があれば受け付けておりますゆえ、遠慮なくお願いします。
特に間違えて習得している部分は教えて頂ければ、本当に助かります。

1.2
あらかじめ、テスト用のプロジェクトは作成しておいて下さい。
参考: Phoenixが欲しいって言うからNode.jsをインスコするよ!!


管理人は、以下の内容で実施しております。
  • アプリケーション名: hello_phoenix
  • 設定は全てデフォルト
  • 作業は、hello_phoenixディレクトリ内で実施(コマンドプロンプトを含む)

2.Viewsの基本的なこと

2.1
ビューの機能簡単に・・・
ビューは、テンプレート(レイアウト含む)をレンダリングする。
また、生データを取得して、それを簡単にテンプレートが処理できるようにする。
Phoenix.Viewモジュールにレンダリング機能が定義されている。

ビューはコントローラから強い命名規則を受ける。
しかしコントローラは、/web/templates/各コントローラのディレクトリに
テンプレートをレンダリングするためビューが必要。

web/web.exのview関数の"use Phoenix.View, root: "web/templates""を変更することで
テンプレートのルートを変更できるようなことが書いてあります。

アプリケーションを作成した時に、デフォルトのビューとして
ErrorView、LayoutView、PageViewが/web/viewsディレクトリに生成される。

2.2
LayoutViewを見てみる。
/web/views/layout_view.exを開く。
----
defmodule HelloPhoenix.LayoutView do
  use HelloPhoenix.Web, :view
end
----

たった三行ですよ。
本当に定義されただけな感じがする。

っと思ったんですけど・・・この一行が・・・
/web/web.exにあるview関数を呼び出しているみたいです。
----
use HelloPhoenix.Web, :view
----

2.3
さて、ちょっと飽きてきたので実行して結果が見れることをやりましょう。
/web/templates/layout/application.html.eexを開き、以下の行を変更します。

変更前: <title>Hello Phoenix!</title>
変更後: <title><%= title %></title>

2.4
次に、/web/views/layout_view.exを開き、
以下の関数を追加しましょう!
----
def title do
  "Awesome New Title!"
end
----

2.5
では、実行してみましょう。
コマンド: mix phoenix.server

あれ・・・どこが変わったの?

あー、ブラウザのタブを見て下さい。
"Awesome New Title!"ってタブが出てるはずです。

しかしなるほど・・・
<%= %>でElixirのコードを実行する方法は前にやりましたね。
コントローラで値を渡した時、似たようなことをやりました。

それが、ビュー側だとこうやって実現できるわけですね。

2.6
少し内容を把握しましょう。
LayoutViewにtitleと言う関数を定義している。
その関数をテンプレートに埋め込み、呼び出している。
そして、実行されたtitle関数が文字列を返して出力して実際の値となっている。

っと言ったところでしょうね。

Tips: HelloPhoenix.LayoutView.titleっと修飾する必要がない。

2.7
さくさく、行きましょう!!
/web/templates/page/index.html.eexを開いて下さい。
以下部分に一行追加します。

追加行: <p><a href="<%= page_path @conn, :index %>">Link back to ourselves</a></p>

変更前
----
<div class="jumbotron">
  <h2>Welcome to Phoenix!</h2>
  <p class="lead">Most frameworks make you choose between speed and a productive environment. <a href="http://phoenixframework.org">Phoenix</a> and <a href="http://elixir-lang.org">Elixir</a> give you both.</p>
</div>
----

変更後
----
<div class="jumbotron">
  <h2>Welcome to Phoenix!</h2>
  <p class="lead">Most frameworks make you choose between speed and a productive environment. <a href="http://phoenixframework.org">Phoenix</a> and <a href="http://elixir-lang.org">Elixir</a> give you both.</p>
  <p><a href="<%= page_path @conn, :index %>">Link back to ourselves</a></p>
</div>
----

2.8
実行してページのHTMLソースを確認してみると・・・こんな出力に変換されています。
<p><a href="/">Link back to ourselves</a></p>

何をやりたかったのかって?
HelloPhoenix.Viewで修飾する必要がないことを示したかった、ただの例です。

つまり・・・ビューを使う時は、
修飾する必要がないってことで、認識してよさそうですね。

3.Viewsについてもっと

3.1
説明がさっぱり分からないので、
百聞は一見に如かずと言いますし、
とりあえず、実例っぽいのをやってみましょう。

/web/view/page_view.exを開き、
以下の関数を追加します。
----
def message do
  "Hello from the view!"
end
----

3.2
次に、/web/templates/pageディレクトリへ
以下の名称のファイルを作成します。
作成ファイル: test.html.eex

以下の内容を記述します。
----
This is the message: <%= message %>
----

3.3
コマンドプロンプトから以下のコマンドを実行します。
コマンド: iex -S mix

対話モードが立ち上がったら、以下の内容を実行する。
iex(1)> Phoenix.View.render(HelloPhoenix.PageView, "test.html", %{})

結果: {:safe, [["" | "This is the message: "] | "Hello from the view!"]}

render関数を使ってPageViewとtest.htmlをレンダリングしているように見えます。
結果の方は・・・test.htmlの内容とmessage関数の結果が出力されていますね。

3.4
/web/templates/page/test.html.eexに
以下の一行を追加して下さい。
----
I came from assigns: <%= @message %>
----

3.5
以下を順番に実行する。
iex(2)> r HelloPhoenix.PageView

結果:
web/views/page_view.ex:1: warning: redefining module HelloPhoenix.PageView
{:reloaded, HelloPhoenix.PageView, [HelloPhoenix.PageView]}

iex(3)> Phoenix.View.render(HelloPhoenix.PageView, "test.html", message: "Assigns has an @.")

結果:
{:safe,
 [[[["" | "I came from assigns: "] | "Assigns has an @."] |
   "\r\nThis is the message: "] | "Hello from the view!"]}

iex(4)> Phoenix.View.render(HelloPhoenix.PageView, "test.html", message: "<script>badThings();</script>")

結果:
{:safe,
 [[[["" | "I came from assigns: "] |
    "&lt;script&gt;badThings();&lt;/script&gt;"] |
   "\r\nThis is the message: "] | "Hello from the view!"]}

iex(5)> Phoenix.View.render_to_iodata(HelloPhoenix.PageView, "test.html", message: "Assigns has an @.")

結果:
[[[["" | "I came from assigns: "] | "Assigns has an @."] |
  "\r\nThis is the message: "] | "Hello from the view!"]

項目自体は、ビューとテンプレートが密接に協力しあっている部分を
説明しようとしているっぽいのだが、実行しても何だかよく分からなかったですね。

その内、分かったらということで先に進みます。

4.レイアウトについて簡単に

4.1
レイアウトについてちょっとやるみたいです。

レイアウトもテンプレートです。
他のテンプレートと同様にビューがあります。
(web/views/layout_view.ex)

テンプレートがレンダリングされると、
LayoutViewはテンプレートのレンダリングされた内容を@innerに割り当てる。

/web/templates/layout/application.html.eexを開いて下さい。
以下の一行を確認してみて下さい。
<%= @inner %>

ここにテンプレートからレンダリングされた文字列が置かれます。

5.ErrorViewについて

5.1
ErrorViewについてですね。

/web/views/error_view.exを開いて、
内容を確認してみましょう。

404(NotFound)と500(内部エラー)の記述がありますね。

5.2
実際に404を見てみたいと思います。
/hello_phoenix/config/dev.exsを開いて以下のように変更する。
(初めて/webの上を参照した気がする・・・)

変更前
----
config :hello_phoenix, HelloPhoenix.Endpoint,
  http: [port: 4000],
  debug_errors: true,
  code_reloader: true,
  cache_static_lookup: false,
  watchers: [node: ["node_modules/brunch/bin/brunch", "watch"]]
----

変更後
----
config :hello_phoenix, HelloPhoenix.Endpoint,
  http: [port: 4000],
  debug_errors: false,
  #code_reloader: true,
  catch_errors: true,
  cache_static_lookup: false,
  watchers: [node: ["node_modules/brunch/bin/brunch", "watch"]]
----

5.3
では、リロードを切っているので、起動中の方は一度終了して・・・
再度、実行します。
コマンド: mix phoenix.server

まずは、普通に"http://localhost:4000"へアクセスする。
次に、"http://localhost:4000/such/a/wrong/path"にアクセスする。
(適当にルーティング先がないアドレスでも問題ないです)

404.htmlに記述してあった文言が見れたと思います。

これですね。
----
def render("404.html", _assigns) do
  "Page not found - 404"
end
----

そもそもこのrender関数どこで呼ばれているの?ってことなのですが、
Phoenix.Endpoint.ErrorHandlerモジュールのレンダリング関数だそうです。

5.4
自分のエラーページを作成してみようとのことです。
と言うわけで、実施してみます。

/web/templatesディレクトリへ新規にディレクトリを作成する。
作成ディレクトリ: error

そのディレクトリに以下の名称のファイルを作成する。
作成ファイル: not_found.html.eex

5.5
以下の内容を記述する。

5.6
/web/views/error_view.exを開き、
404のrender関数を以下のように変更する。
----
def render("404.html", _assigns) do
  render("not_found.html", %{})
end
----

先ほど、iexで実行したrender関数が使われていますね。
微妙につながりました。まだ分かりませんが・・・
だから何って程度ですけど・・・

5.7
では、実行してアクセスしてみましょう。
(/config/dev.exsを元に戻してしまった方は再度設定を行う)

画面の表示が変わりましたね!

しかし、レイアウトを通してレンダリングされていないようですね。
先ほどのHTMLの記述を見ると、
レイアウトに記述されているような内容が記述されていますし・・・

説明を読んでみると・・・
推測の通り、レイアウトを介してnot_found.html.eexテンプレートは
レンダリングされていないようです。

理由としてはグローバルにエラーを処理しながら、
エッジケースの問題を実行するのは簡単だからとのこと。


重複を最小限にしたい場合、ヘッダー、フッターの共有テンプレートの実装が可能。
詳しくは、テンプレートのガイドを見てねっと・・・

以上!!

以下、参考にさせて頂いたサイト様

管理人の独り言~
昨日の記事の説明はひどかったですね・・・疲れて、頭が働かなかったです。
それでも、見てくれている人がいるであろうと思います。
なので、今日も記事をアップする。

かと言って、翻訳能力が付加されるわけでも強化されるわけでもないので、
相変わらずのクソ説明かと思いますが、呆れながらも見てくれると嬉しいです。

人気の投稿