どうも、靖宗です。
今回はControllersということで、コントローラの話です。
ルーティングのところで一通りは把握している所ですが、少々深掘りしていきましょう。
今のところ、Phoenixの作業は
mix phx.new project_name
でプロジェクトを作成- データベース関連の操作(データベース用意したり設定書いたり
mix ecto.create
したり) router.ex
を編集してルーティングを調整controllers
にコントローラを追加views
にビューを追加- 必要であれば
templates
にテンプレートを追加(JSONならたぶんいらない) - 3~6を繰り返し
みたいな流れになりそうです。
コントローラは機能としてはルーティングとレンダリングの橋渡しをする箇所を担っています。
Phoenixプロジェクトを開始した際に入っているlib/hello_web/controllers/page_controller.ex
には下記のように書かれています。
defmodule HelloPhoenixWeb.PageController do use HelloPhoenixWeb, :controller def index(conn, _params) do render(conn, "index.html") end end
コントローラを追加していく時はコレをベースに作成していくのがよさそうです。
また、コントローラもPlugで実装されているようです。
Actions
コントローラでAction
と呼称されているものがありますが、ただの関数です。アクションと関数をわざわざ言い換える必要も無いのですが、アクション関数の目的がレンダリングすることであり、「○○モジュールのレンダリングする関数」と言うのがめんどいのでアクションと呼んでいるに過ぎないのでしょう。
PageController
にデフォルトで備わっているアクションは:index
で、ルーティングファイルから下記のように呼び出されています。
get "/", PageController, :index
テスト用には:test
というアクションが想定されているようです。
get "/", PageController, :test
コントローラにテストを追加するならこんなかんじ
defmodule HelloPhoenixWeb.PageController do use HelloPhoenixWeb, :controller ... def test(conn, _params) do render(conn, "index.html") end end
まぁ、現段階ではテストになってないんですが。
アクションの命名自体は自由だそうですが、ルーティングの章でResourcesをやりました。これを鑑みると下記のアクション名は機能をResourcesに揃えておくのが望ましいでしょう。
- index
- リソースのアイテムを全表示する
- show
- IDで識別されるアイテムを表示する
- new
- 新しいアイテムを作成する画面を表示する
- create
- 新しいアイテムを作成する変数を受けてデータベースなどに保存する(表示自体はリダイレクト?)
- edit
- 編集するIDの変数を取り出す+編集できるフォームを表示する
- update
- 編集するアイテムの変数を受けてデータベースなどに上書き保存する
- delete
- 削除するIDを受けてデータベースから削除する(確認画面なんかも出した方がいい?)
アクションは基本的に2つ引数をとります。1個目はconn
という事でPlugのところで出てきている接続情報(%Plug.Conn{}
)です。
これはコントローラがPlugで実装されているからでしょう。
2個目の引数はparams
で、必要に応じてHTTPリクエストからパラメータを取り出すマップとなっています。
Adding Pagesの章でやりましたが、ルーティングの際に
get "/hello/:messenger", HelloController, :show
と書かれている場合はリクエストが来た場合にparams
に"messenger"
というキーで値が入っています。
例えばhttp://localhost:4000/hello/hogefuga
というアドレスにアクセスがあった場合には、params
には"messenger"
というキーに"hogefuga"
が値として渡されます。
これをコントローラで
defmodule HelloPhoenixWeb.PageController do ... def show(conn, %{"messenger" => messenger}) do render(conn, "show.html", messenger: messenger) end end
というふうに、パターンマッチングで受けるのがPhoenixの習わしっぽいです。
:index
アクションの様にパラメータが不要な際は_params
と”関数の実行に関わりの無い引数”としておくのが良いでしょう。(Elixirのならわし)
Gathering Data
データのストア(記録、読み出しなど)機能はPhoenixの機能としては実装してないようです。
それもそのはず、Ecto
というデータベースラッパーがElixirには存在しているらしく、そちらを使うと良いよ!と記載があります。
なので、基本的には
という流れになると思います。
実際に開発を進めるに当たってEctoも重要になってきそうですので、また別途記事にしたいと思います。
Flash Messages
Flash Messagesという機能があるようです。フロントでもちょいちょい見たような?
SPAなどでよくある「ログインに失敗しました」みたいなのがぴょこっと出てきて画面遷移しない時とかに使う奴だと思います。
コントローラを使える状態であればput_flash/3
とget_flash/2
でメッセージのやりとりができるようです。サンプルを見てみます。
defmodule HelloPhoenixWeb.PageController do ... def index(conn, _params) do conn |> put_flash(:info, "Welcome to Phoenix, from flash info!") |> put_flash(:error, "Let's pretend we have an error.") |> render("index.html") end end
put_flash/3
の第一引数はパイプラインですので接続情報、第二引数はメッセージのキー、第三引数はメッセージのバリューという関数でしょう。
特にキー名などの制約はないようですが、:info
と:error
はよく使われるようです。
表示するときはテンプレートでget_flash/2
を使うようです。
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p> <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
第一引数が接続情報、第二引数がキーというかんじです。
他にもclear_flash/1
という関数もあるようですが、このへんはFlash Messagesを使いたくなったら検討しましょう。
なんとなくフロント側で処理する方がスッキリする気がします。
Controllersちょっと長いので一旦ここで区切ります。