4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

phx.gen.jsonでAPIを生成する

Last updated at Posted at 2023-10-24

phx.gen.jsonでAPIを生成する

mix phx.gen.jsonというコマンドを使用すると、
Schemaと基本的なCRUDを行うAPIを生成することができる。

以下の作業を行い、生成したAPIを利用できるようにする。

  1. mix phx.gen.jsonの実行
  2. 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.exrender()で使用する出力形式を定義している。

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プロジェクトの生成時にErrorHTMLErrorJSONが生成されているのでこれを指定する。

{: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.expipelineとはplugをまとめたのことである。

pipe_throughでスコープごとに実行するpipelineを指定することができる。。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?