Part 6 · 1 chapters · ~8 min
Phoenix End to End
Generating a Phoenix app, the endpoint and plugs, the router and pipelines, controllers and JSON views, contexts as domain boundaries, Ecto schemas, changesets, queries, migrations and Ecto.Multi, authentication (phx.gen.auth), Channels, PubSub, and building the transfers API.
7
A transfers endpoint
code
mix phx.new ledger --no-html --no-assets && cd ledger && mix ecto.create
# router.ex
scope "/v1", LedgerWeb do
pipe_through [:api, :require_api_key]
post "/transfers", TransferController, :create
end
# transfer_controller.ex: thin
def create(conn, params) do
key = get_req_header(conn, "idempotency-key") |> List.first()
with {:ok, transfer} <- Ledger.create_transfer(params, key) do
conn |> put_status(:created) |> json(%{id: transfer.id, state: transfer.state})
end
end
# ledger.ex: the context, one transaction for the whole operation
def create_transfer(params, key) do
Ecto.Multi.new()
|> Ecto.Multi.insert(:idem, IdempotencyKey.changeset(%{key: key}), on_conflict: :nothing, conflict_target: :key)
|> Ecto.Multi.run(:transfer, fn repo, %{idem: idem} -> maybe_create(repo, idem, params) end)
|> Repo.transaction()
endA PHOENIX REQUEST
endpoint, router, pipeline, controller, context, Ecto
swipe the figure sideways, or tap expand for full screen
1/4
plugs
A request flows through a pipeline of plugs (composable functions on a connection): parsing, sessions, auth, telemetry.
everything is a plugPlug.Conn