スポンサーリンク

2015年6月5日

Phoenixのテンプレート(Templates)について分かったこと

タイトル: Phoenixのテンプレート(Templates)について分かったこと

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

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

目次:

  1. 概要
  2. Templatesの基本的なこと
  3. (web.ex)メインビューを使ってみる?
  4. (Displaying Lists)リストはどうやって表示したらいいの?
  5. (Render templates within templates)テンプレートの中のテンプレート
  6. (Shared Templates Across Views)テンプレートの共有

1.概要

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

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

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

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

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

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

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


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

2.Templatesの基本的なこと

2.1
はい、Phoenixのテンプレートについてです。

HTTPのレスポンスを形成するためにデータを渡す。
Webアプリケーションの大体のレスポンスは、HTMLドキュメントだろう。
しかし、JSONやXMLである可能性もある。

テンプレートファイルの大部分はマークアップだが、
Elixirコードを記述している場合もある。

Phoenixのテンプレートは事前にコンパイルされている。
そのため、非常に高速である。

PhoenixのテンプレートシステムはRubyのERBと似ている。
実際には、Elixir自体の一部である。

View Guidesでやったように、
各テンプレートには、View名にちなんで名付けられたディレクトリが必要。
また、デフォルトでは/web/templates配下に配置する。

テンプレートをレンダリングするため、各Viewモジュールがある。

3.(web.ex)メインビューを使ってみる?

3.1
アプリケーションのメインビュー。

/web/web.exファイルにおける、
Viewブロック内の宣言の全ては全テンプレートに適応されるとのこと。

3.2
さてさて、ではちょっとアプリケーションに追加を行い、試してみましょう。
まずは、新しいルーティング先を追加します。

/web/router.exを開き、以下のように編集して下さい。
----
scope "/", HelloPhoenix do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
  get "/test", PageController, :test
end
----

3.3
次は、PageControllerへtestアクションを追加します。
----
def test(conn, _params) do
  render conn, "test.html"
end
----

3.4
続いて、/web/web.exを開き、以下の行を編集します。
変更前: import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
変更後: import Phoenix.Controller, only: [get_flash: 2, action_name: 1, controller_module: 1]

3.5
次に、/web/views/page_view.exを以下のように編集します。
----
defmodule HelloPhoenix.PageView do
  use HelloPhoenix.Web, :view

  def handler_info(conn) do
    "Request Hendled By: #{controller_module conn}.#{action_name conn}"
  end

  def connection_keys(conn) do
    conn
    |> Map.from_struct()
    |> Map.keys()
  end
end
----

3.6
ルーティング先を作り、コントローラにアクションを定義し、
アプリケーションのメインビューへ変更を行いました。

後、足りないのは・・・そう!テンプレートファイルですね!!
別に大した内容を記述してるわけではないみたいですけど・・・

/web/templates/pageディレクトリへ以下のファイルを作成する。
作成ファイル: test.html.eex

内容は以下の通り。
----
<div class="jumbotron">
  <p><%= handler_info @conn %></p>
</div>
----

3.7
では実行してみましょう。
コマンド: mix phoenix.server
アドレス: http://localhost:4000/test

"Request Hendled By: Elixir.HelloPhoenix.PageController.test"
上記の文言が表示されていますね。

3.8
我々は、/web/views内のビューで関数を定義することができる。
その関数は、レンダリングするテンプレートで使用することができるようになる。
例えば、hendler_infoがその例です。(connection_keysはどうしたんだ?)

さて、私の理解が追いついていないので少し振り返ります。

  1. router.exへ新しいルーティング先の設定をした
  2. PageControllerにtestアクションを定義した
  3. web.ex(メインビュー)内の"import Phoenix.Controller..."を編集した
  4. PageViewへhandler_info、connection_keysを定義した
  5. test.html.eexでhandler_infoを呼び出した
  6. 実行結果または動作としては、実行したコントローラとアクションを取得し表示している

っと言ったところでしょう。
細かい部分に関しては疑問が多々ありますが、
この項目には書いていないのか、はたまた自分が読めていないだけなのか・・・
不明な部分を残すところです。

4.(Displaying Lists)リストはどうやって表示したらいいの?

4.1
テンプレート内に私たちが定義した値を表示しました。
では、リストはどのようにして全ての要素を表示させればよいでしょうか?

つまり、リストで渡すものの表示方法どうすんの?
っと言うのがこの項目のようですね。

実例、実例~動くものがあるのは、やっぱりいいですね~

4.2
/web/templates/page/test.html.eexを開いて、
内容を以下のように編集します。
----
<div class="jumbotron">
  <p><%= handler_info @conn %></p>

  <h3>Keys for the conn Struct</h3>

  <%= for key <- connection_keys @conn do %>
    <p><%= key %></p>
  <%= end %>
</div>
----

4.3
connection_keys関数出てきましたね。

では実行してみましょう。
コマンド: mix phoenix.server
アドレス: http://localhost:4000/test

画面表示を確認すると・・・
何か、いっぱい出てきましたね。

動作を見るにconnection_keys関数は、
conn構造体のkeysを抽出して、返してるといったところでしょうか。

そして、テンプレートの方でループで一つずつ各keyを出力させている。
そんなところでしょう。

5.(Render templates within templates)テンプレートの中のテンプレート

念の為言っておくが、男の中の漢みたいなものではない!!
全く関係ないのであしからずw

5.1
直訳すると・・・テンプレート内のテンプレートをレンダリング?

何だかテンプレートに
<p><%= key %></p>
ってあると読みにくいよね的なことを言ってます。

解決方法が、別のテンプレートを呼び出してレンダリングすればよいと・・・
関数のように呼び出せるとのこと。

レンダリングチェーンの一種だそうです。
分かりやすい例としてはレイアウトのテンプレートで別のテンプレート読んでますよね?
あんな感じでできるそうです。

となれば、機能ごとにテンプレートを分割して、
小さいテンプレートを組み合わせて表示ができるのでは?

んで、通常のテンプレートも他のテンプレートを有してよいっと!
んでんで、どうやってやるの?

5.2
まず、新しくテンプレートを作成します。(/web/templates/pageディレクトリへ)
作成ファイル: key.html.eex

内容は以下の通り!!
----
<p><%= @key %></p>
----

@が付く理由~
この新しいテンプレートは、
リスト内包表記の一部ではないため、
@keyとしなければ参照できない。

通常、テンプレートにデータを渡す方法は、
割り当てマップであり、割り当てマップから値を取得する方法は、
先行する@でキーを参照しなければならないからである。

5.3
/web/templates/page/test.html.eexを開き、以下の行を編集する。
変更前: <p><%= key %></p>
変更後: <%= render "key.html", key: key %>

5.4
はい、では実行して下さい。
コマンド: mix phoenix.server
アドレス: http://localhost:4000/test

表示は変わりませんね。

6.(Shared Templates Across Views)テンプレートの共有

6.1
現在のビューからレンダリングしているテンプレートがある。
これをテンプレートAとしよう・・・

そのテンプレートAから別のテンプレートを呼び出す。
この呼び出すテンプレートはテンプレートBとしよう・・・

テンプレートBを別のビューでレンダリングする。
と言うのがこの項目のようだ。

つまり、今のビューと別のビューでレンダリングされているテンプレートを
呼び出すにはどうやって行うのかやっていく項目。

実例を実施して動かしてみましょう。

6.2
/web/viewsディレクトリへ以下のファイルを作成する。
作成ファイル: shared_view.ex

内容は以下の通り。
----
defmodule HelloPhoenix.SharedView do
  use HelloPhoenix.Web, :view
end
----

6.3
/web/templatesディレクトリへ新しいディレクトリを作成する。
作成ディレクトリ: shared

/web/templates/page/key.html.eexを上記で作成したディレクトリへ移動する。
変更前: /web/templates/page/key.html.eex
変更後: /web/templates/shared/key.html.eex

6.4
/web/templates/page/test.html.eexを開き、以下の行を編集する。
変更前: <%= render "key.html", key: key %>
変更後: <%= render HelloPhoenix.SharedView, "key.html", key: key %>

6.5
そして実行する。
コマンド: mix phoenix.server
アドレス: http://localhost:4000/test

以前と同じ表示結果が画面に出力されていればおーるおーけー!!

Tips
SharedViewではなく、PageViewを使ってレンダリングしていた時、
呼び出し部分を明示的にすると以下のような形になる。
----
<%= for key <- connection_keys @conn do %>
  <%= render HelloPhoenix.PageView, "key.html", key: key %>
<% end %>
----

お疲れ様でした~、以上!!

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

管理人の独り言~
Elixir強化週間もあと少しを残すところとなった。
毎日更新はまだ続く・・・そろそろ疲れてきたのだが・・・
まだだ!まだやれる!!今週の日曜日まで頑張ればいいんだ!!!!

後は、ChannelとPlugあたりを理解しないとね~。
そして、掲示板もどきを作成~っと。
多分、強化週間中には到達しないと思うけどね。

人気の投稿