phx.gen.json
でAPIを生成する
mix phx.gen.json
というコマンドを使用すると、
Schemaと基本的なCRUDを行うAPIを生成することができる。
以下の作業を行い、生成したAPIを利用できるようにする。
-
mix phx.gen.json
の実行 -
router.ex
に追記
mix phx.gen.json
を実行することで、/controllers
以下に次のファイルが生成される。
*_controller.ex
*_json.ex
fallback_controller.ex
changeset_json.ex
router.exには画面のしたがって記述するとよい。
*_controller.ex
とは
mix phx.routes
を実行すると、ルートが追加されている確認できる。
*_controller.ex
は、このルートに対するアクションを定義している。
*_json.ex
とは
pipeline :api
にはplug :accepts, ["json"]
と記述されている。
このルートのレスポンスのコンテンツタイプはJSONとなり、
よってViewはJSONモジュールとなる。
このモジュールでは*_contoller.ex
のrender()
で使用する出力形式を定義している。
indexアクションのルートに対しcurl
でリクエストを送信すると、ここで定義した形式で出力されることが確認できる。
curl http://localhost:4000/api/users
{"data":[]}
使用例
ここでは以下を実行し、出力を変更していない場合とする。
mix phx.gen.json Users User users name:string age:integer
// index 実行
curl http://localhost:4000/api/users
// index 出力
{"data":[]}
// create 実行
curl -X POST -H 'Content-Type: application/json' -d '{"user": {"name" : "Taro", "age" : "32"}}' http://localhost:4000/api/users
// show 実行
curl http://localhost:4000/api/users/1
// show 出力
{"data":{"id":1,"name":"Taro","age":32}}
// update 実行
curl -X PATCH -H 'Content-Type: application/json' -d '{"user" : {"age" : "41"}}' http://localhost:4000/api/users/1
// update 出力
{"data":{"id":1,"name":"Taro","age":41}}
// delete 実行
curl -X DELETE http://localhost:4000/api/users/1
fallback_controller.ex
とは
コントローラのアクションが失敗したときに呼び出される処理を定義している。
action_fallback
という記述でフォールバックコントローラとして呼び出されている。
このモジュールには2つのcall()
が定義されている。
call(conn, {:error, %Ecto.Changeset{} = changeset})
call(conn, {:error, :not_found})
コントローラーのアクションで呼び出される関数を確認する。
関数にエラー時に次のエラータプル、または例外を発生している
{:error, %Ecto.Changeset{}}
Ecto.NoResultsError
このような場合にフォールバックコントローラによるフォールバック処理が行われる。
call(...)
は以下のように記述される。
def call(conn, ...) do
conn
|> put_status(ステータスコード)
|> put_view(ビュー)
|> render(テンプレート)
end
put_status/2
は、エラーコードを整数またはアトムを指定できる。
エラーコードは整数、アトムはPlug.Conn.Statusで定義されたものが使用できる。
put_view/2
は、ビューを指定する。
html: HTMLビュー, json: JSONビュー
と記述する。
Phoenixプロジェクトの生成時にErrorHTML
とErrorJSON
が生成されているのでこれを指定する。
{:error, %Ecto.Changeset{}}
アクションではwith
句によるパターンマッチが行われている。
with {:ok, %User{} = user} <- Users.create_user(user_params) do
conn
|> put_status(:created)
|> put_resp_header("location", ~p"/api/users/#{user}")
|> render(:show, user: user)
end
パターンマッチしない場合は、値をそのまま返す。
そのためEctoによる更新処理に失敗した場合、
アクションは{:error, %Ecto.Changeset{}
を出力し、コールバック処理が呼び出される。
Ecto.NoResultsError
この例外はRepo.get!()
などで発生する可能性のある例外である。
実際にこの例外が発生するようAPIを呼び出してみると、iexに以下のでデバックログが出力されている。
[debug] Converted error Ecto.NoResultsError to 404 response
Phoenixでは特定の例外は、このように変換される(らしい)。
よってこの例外が発生したときは、アクションは{:error, :not_found}
が出力される。
なおこれ以外のEcto例外は、デフォルトの動作と同様{:error, :internal_server_error}}
が出力される(らしい)。
changeset_json.ex
とは
Ecto.Changesetからエラー文を抽出し、jsonとして返すためのビュー
用語
pipeline
plugとはアクションを実行する前処理のことである。
router.ex
のpipeline
とはplugをまとめたのことである。
pipe_throughでスコープごとに実行するpipeline
を指定することができる。。