タイトル: Phoenixのコントローラ(Controllers)について分かったこと(その2)
目的: Phoenixアプリケーションのコントローラ(Controllers)について分かったことを記述する。
実施環境:
OS: Windows8.1Erlang: Eshell V6.4
Elixir: v1.0.4
Phoenix Framework: v0.13.1
Node.js: v0.12.4
目次:
- 概要
- Assigning Layoutsの使い方
- Overriding Rendering Formatsの使い方
- Setting the Content Typeの使い方(未完成)
- Setting the HTTP Statusの使い方
- Redirectionの使い方
1.概要
1.1
注意!!
この記事は、Phoenix - Guides ControllersをGoogle翻訳を使い、分かったことを書いています。
原文を丸々翻訳しているわけではないので、
流れや説明がおかしいところ多々ありますが、その点注意して下さい。
原文を丸々翻訳しているわけではないので、
流れや説明がおかしいところ多々ありますが、その点注意して下さい。
英語が分かる方は、公式ガイドを見た方が確実です。
また、管理人の英語力は本人がドン引きするほど低いので、
間違った解釈及び理解している部分が多分にあると思います。
それでも構わないという方は見て頂けたら嬉しいです。
また、ご指摘等があれば受け付けておりますゆえ、遠慮なくお願いします。
特に間違えて習得している部分は教えて頂ければ、本当に助かります。
全てのテンプレートがデフォルトでレンダリングされるレイアウト。
/web/templates/layout/application.html.eex
レイアウトはただのテンプレートなので、
レンダリングしてくれるビューを必要とする。
上記のテンプレートに対応しているのは、
/web/views/layout_view.exで定義されているLayoutViewモジュール。
Phoenix.Controllerモジュールのput_layout機能を使用する。
第一引数は、レイアウトのベース名を文字列を取る。
第二引数は、booleanを取る。
例のソースコードだと、
第一引数を取ってなかったり、
trueとfalseで何が変わるのとか、
書いてないから引数よく分からない。
/web/controllers/page_controller.exを開き、
indexアクションを以下のように修正する。
----
def index(conn, params) do
conn
|> put_layout(false)
|> render "index.html"
end
----
実行したけど、表示がいきなりしょぼくなったな・・・
なんか、重要!!とかって書かれてる部分がある。
put_layout使う時は、()で引数囲うこと・・・とか。
つまり、"put_layout false"と言った記述はダメらしい。
/web/templates/layoutディレクトリに以下の名称のファイルを作成する。
内容は、同ディレクトリのapplication.html.eexをコピーするので、
ファイル自体をコピーしてリネームでもいいですね。
作成ファイル: admin.html.eex
んで、作成したファイルから以下の行を削除する。
<span class="logo"></span>
先ほど作成したファイルを指定してみる。
----
def index(conn, params) do
conn
|> put_layout("admin.html")
|> render "index.html"
end
----
実行すると、ロゴなしの画面が出てきましたね。
この項目はよく分からなかった。
一応実行できたので、何となくは分かるのですが、割かし曖昧です。
そのことを念頭に置いて読んで下さい。(飛ばしても結構です)
レンダリングしたい対象がテキストやJSON、HTMLである時の方法について書いてあるっぽい。
んで、この機能は・・・
フォーマットクエリ文字列パラメータを使用してその場でフォーマットを変更できる。
また、使用するには・・・
適切な名前のビューと適切なディレクトリに適切な名前のテンプレートが必要とのこと。
/web/templates/pageディレクトリへ新規にファイルを作成する。
作成ファイル: index.text.eex
内容は以下の一文(普通にテキストファイルですね)
"OMG, this is actually some text."
pipeline :browserを以下のように修正する。
----
pipeline :browser do
plug :accepts, ["html", "text"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
end
----
ここで扱えるフォーマット?を追加している。
修正前: plug :accepts, ["html"]
修正後: plug :accepts, ["html", "text"]
テキストが増えてますね。
indexアクションを以下のように修正する。
----
def index(conn, _params) do
render conn, :index
end
----
では実行して表示を確認する。
この段階では、画面内容は変わっていませんね。
"render conn, :index"にご注目。
"index.html"が:indexになっていますね。
これは、:indexで指定していると、自動でindex.html.eesがレンダリングされているみたいですね。
ここ、原文読んでもよく分からなかったのです。
テキストのテンプレートでもデータを渡すことができることをやるみたいですね。
再び、indexアクションを以下のように修正して下さい。
----
def index(conn, params) do
render conn, "index.text", message: params["message"]
end
----
テキストファイルを指定してますね。また、messageで値を渡してますね。
ところで、気付いた方いますでしょうかparamsに_がありません。
_なしでparamsの使用がないと警告が出ます。だから、使わない時は_を付けるみたいですね。
例)
web/controllers/page_controller.ex:6: warning: variable params is unused
/web/templates/page/index.text.eexを開き、以下のように修正する。
"OMG, this is actually some text." <%= @message %>
以下のアドレスにアクセスして下さい。
アドレス: http://localhost:4000/?format=text&message=CrazyTown
フォーマットの指定とmessageの値をURLの中に入れてます。
また、ヘッダーを受け入れ、適切なテンプレートを提供する必要があるっと・・・
よく分かりませんねw
物は試しと言うことで実行しましょう。
indexアクションでXMLをレンダリングしたい場合。
すいません、エラーが出て直せません・・・
その内分かったら記述します。
有効なコンテンツのMIMEタイプは別のドキュメントを参照すること
参考: https://github.com/elixir-lang/plug/blob/master/lib/plug/mime.types
思いました・・・Overriding Rendering Formatsでできないんでしょうか?
まぁ、いずれ検証するとして今は項目を消化してしまいましょう。
関数名が違うのでまた違うのでしょうが・・・
応答のHTTPステータスコードを設定する方法。
Plug.Connモジュールをインポートして、put_status関数を使用する。
参考: https://github.com/elixir-lang/plug/blob/master/lib/plug/conn/status.ex#L7-L63
/web/controllers/page_controller.exを開き、
indexアクションを以下のように修正する。
----
def index(conn, _params) do
conn
|> put_status(202)
|> render "index.html"
end
----
実行して、HTTPステータスを確認する。
----
def index(conn, _params) do
conn
|> put_status(:not_found)
|> render "index.html"
end
----
実行して、HTTPステータスを確認する。
HTTPステータスは404not_foundなのに、ページはindex.htmlですね。
----
def index(conn, _params) do
conn
|> put_status(:not_found)
|> render(HelloPhoenix.ErrorView, "404.html")
end
----
実行する。
Phoenixのロゴの下に"Page not found"と表示されましたね。
つまり、HTTPステータスは送れるけど、実際のレンダリングには関係ないよってことらしい。
レンダリングの切り替えは行う必要があるってことですね。
しかし、PageControllerの適切なビューはPageViewのはずなのに、
ErrorViewが出てくるってどうなっているんでしょうか?
疑問点ですね・・・
リダイレクトのさせ方ですね。
リダイレクト関数があるみたいですね。
アプリケーション内のパスへのリダイレクトと
URLにリダイレクトするのは区別するようです。
----
scope "/", HelloPhoenix do
get "/redirect_test", PageController, :redirect_test, as: :redirect_test
end
----
以下が追加されていますね。
redirect_test_path GET /redirect_test HelloPhoenix.PageController.redirect_test/2
indexアクションを以下のように修正する。
アプリケーション内のパスを指定してリダイレクトするやり方です。
def index(conn, _params) do
redirect conn, to: "/redirect_test"
end
また、redirect_testアクションを新しく追加する。
def redirect_test(conn, _params) do
text conn, "Redirect!"
end
実行します。"localhost:4000"にアクセスして下さい。
Redirect!と表示されますね。
まず、indexアクションが実行され、/redirect_testのパスへリダイレクトしてます。
その後、redirect_testアクションが実行され、textで出力しています。
開発者ツールを使ってHTTPステータスを確認してみると実際に動きが見れます。
URLを指定してリダイレクトさせるやり方です。
----
def index(conn, _params) do
redirect conn, external: "http://elixir-lang.org/"
end
----
はい、実行。
Elixirのサイトへリダイレクトしましたね。
----
defmodule HelloPhoenix.PageController do
use HelloPhoenix.Web, :controller
def index(conn, _params) do
redirect conn, to: redirect_test_path(conn, :redirect_test)
end
end
----
実行。
再び、Redirect!と表示されますね。
URLをPathHelpersで指定する。
----
def index(conn, _params) do
redirect conn, external: redirect_test_url(conn, :redirect_test)
end
----
ry
Redirect!と表示されます。
URLの指定は必ずしも外部でなくて構わないみたいです。
ちなみに、external:をto:に変更すると失敗します。
1.2
あらかじめ、テスト用のプロジェクトは作成しておいて下さい。
参考: Phoenixが欲しいって言うからNode.jsをインスコするよ!!
もしくは、その1を実施して下さい。
参考: Phoenixのコントローラ(Controllers)について分かったこと(その1)
※ その1は実施していなくても、その2の実施に問題はありません。
もしくは、その1を実施して下さい。
参考: Phoenixのコントローラ(Controllers)について分かったこと(その1)
※ その1は実施していなくても、その2の実施に問題はありません。
2.Assigning Layoutsの使い方
2.1
Phoenixが生成した、レイアウトのテンプレート。全てのテンプレートがデフォルトでレンダリングされるレイアウト。
/web/templates/layout/application.html.eex
レイアウトはただのテンプレートなので、
レンダリングしてくれるビューを必要とする。
上記のテンプレートに対応しているのは、
/web/views/layout_view.exで定義されているLayoutViewモジュール。
2.2
レイアウトを切り替えるためには、Phoenix.Controllerモジュールのput_layout機能を使用する。
第一引数は、レイアウトのベース名を文字列を取る。
第二引数は、booleanを取る。
例のソースコードだと、
第一引数を取ってなかったり、
trueとfalseで何が変わるのとか、
書いてないから引数よく分からない。
2.3
何れにせよ、実際に使ってみよう。/web/controllers/page_controller.exを開き、
indexアクションを以下のように修正する。
----
def index(conn, params) do
conn
|> put_layout(false)
|> render "index.html"
end
----
実行したけど、表示がいきなりしょぼくなったな・・・
なんか、重要!!とかって書かれてる部分がある。
put_layout使う時は、()で引数囲うこと・・・とか。
つまり、"put_layout false"と言った記述はダメらしい。
2.4
続き、行きましょう・・・/web/templates/layoutディレクトリに以下の名称のファイルを作成する。
内容は、同ディレクトリのapplication.html.eexをコピーするので、
ファイル自体をコピーしてリネームでもいいですね。
作成ファイル: admin.html.eex
んで、作成したファイルから以下の行を削除する。
<span class="logo"></span>
2.5
/web/controllers/page_controller.exのindexアクションで先ほど作成したファイルを指定してみる。
----
def index(conn, params) do
conn
|> put_layout("admin.html")
|> render "index.html"
end
----
実行すると、ロゴなしの画面が出てきましたね。
3.Overriding Rendering Formatsの使い方
3.1
あらかじめ、書いておきます。この項目はよく分からなかった。
一応実行できたので、何となくは分かるのですが、割かし曖昧です。
そのことを念頭に置いて読んで下さい。(飛ばしても結構です)
レンダリングしたい対象がテキストやJSON、HTMLである時の方法について書いてあるっぽい。
んで、この機能は・・・
フォーマットクエリ文字列パラメータを使用してその場でフォーマットを変更できる。
また、使用するには・・・
適切な名前のビューと適切なディレクトリに適切な名前のテンプレートが必要とのこと。
3.2
実際にやってみる。/web/templates/pageディレクトリへ新規にファイルを作成する。
作成ファイル: index.text.eex
内容は以下の一文(普通にテキストファイルですね)
"OMG, this is actually some text."
3.3
/web/router.exを開き、pipeline :browserを以下のように修正する。
----
pipeline :browser do
plug :accepts, ["html", "text"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
end
----
ここで扱えるフォーマット?を追加している。
修正前: plug :accepts, ["html"]
修正後: plug :accepts, ["html", "text"]
テキストが増えてますね。
3.4
/web/controllers/page_controller.exを開き、indexアクションを以下のように修正する。
----
def index(conn, _params) do
render conn, :index
end
----
では実行して表示を確認する。
この段階では、画面内容は変わっていませんね。
"render conn, :index"にご注目。
"index.html"が:indexになっていますね。
これは、:indexで指定していると、自動でindex.html.eesがレンダリングされているみたいですね。
ここ、原文読んでもよく分からなかったのです。
3.5
次は、テンプレートにテキストファイルを指定します。テキストのテンプレートでもデータを渡すことができることをやるみたいですね。
再び、indexアクションを以下のように修正して下さい。
----
def index(conn, params) do
render conn, "index.text", message: params["message"]
end
----
テキストファイルを指定してますね。また、messageで値を渡してますね。
ところで、気付いた方いますでしょうかparamsに_がありません。
_なしでparamsの使用がないと警告が出ます。だから、使わない時は_を付けるみたいですね。
例)
web/controllers/page_controller.ex:6: warning: variable params is unused
3.6
次に、/web/templates/page/index.text.eexを開き、以下のように修正する。
"OMG, this is actually some text." <%= @message %>
3.7
ここまで来たら、実行して下さい。以下のアドレスにアクセスして下さい。
アドレス: http://localhost:4000/?format=text&message=CrazyTown
フォーマットの指定とmessageの値をURLの中に入れてます。
4.Setting the Content Typeの使い方(未完成)
4.1
HTTPを変更することにより、必要なフォーマットの任意の並べ替えをレンダリングできるらしい・・・また、ヘッダーを受け入れ、適切なテンプレートを提供する必要があるっと・・・
よく分かりませんねw
物は試しと言うことで実行しましょう。
indexアクションでXMLをレンダリングしたい場合。
すいません、エラーが出て直せません・・・
その内分かったら記述します。
有効なコンテンツのMIMEタイプは別のドキュメントを参照すること
参考: https://github.com/elixir-lang/plug/blob/master/lib/plug/mime.types
思いました・・・Overriding Rendering Formatsでできないんでしょうか?
まぁ、いずれ検証するとして今は項目を消化してしまいましょう。
5.Setting the HTTP Statusの使い方
5.1
何か前に似たようなのやりましたね。send_respでしたっけ?関数名が違うのでまた違うのでしょうが・・・
応答のHTTPステータスコードを設定する方法。
Plug.Connモジュールをインポートして、put_status関数を使用する。
参考: https://github.com/elixir-lang/plug/blob/master/lib/plug/conn/status.ex#L7-L63
5.2
使ってみよう。/web/controllers/page_controller.exを開き、
indexアクションを以下のように修正する。
----
def index(conn, _params) do
conn
|> put_status(202)
|> render "index.html"
end
----
実行して、HTTPステータスを確認する。
5.3
次、以下のように修正する。----
def index(conn, _params) do
conn
|> put_status(:not_found)
|> render "index.html"
end
----
実行して、HTTPステータスを確認する。
HTTPステータスは404not_foundなのに、ページはindex.htmlですね。
5.4
なので、エラーページを出すために以下のように修正する。----
def index(conn, _params) do
conn
|> put_status(:not_found)
|> render(HelloPhoenix.ErrorView, "404.html")
end
----
実行する。
Phoenixのロゴの下に"Page not found"と表示されましたね。
つまり、HTTPステータスは送れるけど、実際のレンダリングには関係ないよってことらしい。
レンダリングの切り替えは行う必要があるってことですね。
しかし、PageControllerの適切なビューはPageViewのはずなのに、
ErrorViewが出てくるってどうなっているんでしょうか?
疑問点ですね・・・
6.Redirectionの使い方
6.1
あえて、書きます。リダイレクトのさせ方ですね。
リダイレクト関数があるみたいですね。
アプリケーション内のパスへのリダイレクトと
URLにリダイレクトするのは区別するようです。
6.2
/web/router.exを開き、新しくscope(ルート)を追加する。----
scope "/", HelloPhoenix do
get "/redirect_test", PageController, :redirect_test, as: :redirect_test
end
----
6.3
"mix phoenix.routes"コマンドを使い、ルーティングを見てみます。以下が追加されていますね。
redirect_test_path GET /redirect_test HelloPhoenix.PageController.redirect_test/2
6.4
/web/controllers/page_controller.exを開き、indexアクションを以下のように修正する。
アプリケーション内のパスを指定してリダイレクトするやり方です。
def index(conn, _params) do
redirect conn, to: "/redirect_test"
end
また、redirect_testアクションを新しく追加する。
def redirect_test(conn, _params) do
text conn, "Redirect!"
end
実行します。"localhost:4000"にアクセスして下さい。
Redirect!と表示されますね。
まず、indexアクションが実行され、/redirect_testのパスへリダイレクトしてます。
その後、redirect_testアクションが実行され、textで出力しています。
開発者ツールを使ってHTTPステータスを確認してみると実際に動きが見れます。
6.5
今度は、indexアクションを以下のように修正して下さい。URLを指定してリダイレクトさせるやり方です。
----
def index(conn, _params) do
redirect conn, external: "http://elixir-lang.org/"
end
----
はい、実行。
Elixirのサイトへリダイレクトしましたね。
6.6
続いてPathHelpersを使ったやり方です。----
defmodule HelloPhoenix.PageController do
use HelloPhoenix.Web, :controller
def index(conn, _params) do
redirect conn, to: redirect_test_path(conn, :redirect_test)
end
end
----
実行。
再び、Redirect!と表示されますね。
6.7
最後です。URLをPathHelpersで指定する。
----
def index(conn, _params) do
redirect conn, external: redirect_test_url(conn, :redirect_test)
end
----
ry
Redirect!と表示されます。
URLの指定は必ずしも外部でなくて構わないみたいです。
ちなみに、external:をto:に変更すると失敗します。
以上!!
以下、参考とさせて頂いたサイト様
管理人の独り言~
長々とその1からお疲れ様でした。
目を通して頂いた方はありがとうございます。
まだ、分かってないことはありますが・・・
まぁ、追々と言うことで・・・
また分かったら追記もしくは記事を書きますので・・・
長々とその1からお疲れ様でした。
目を通して頂いた方はありがとうございます。
まだ、分かってないことはありますが・・・
まぁ、追々と言うことで・・・
また分かったら追記もしくは記事を書きますので・・・