Current section

Files

Jump to
caravela priv templates controller.eex
Raw

priv/templates/controller.eex

defmodule <%= inspect @controller_module %> do
@moduledoc """
Generated by Caravela from <%= inspect @domain_module %>.
JSON controller for `<%= @entity_name %>`. All actions build a
`context` map from `conn.assigns` and delegate to `<%= inspect @context_module %>`.
Regenerate with `mix caravela.gen.api <%= inspect @domain_module %>`.
Custom code placed below the `# --- CUSTOM ---` marker is preserved.
"""
use Phoenix.Controller, formats: [:json]
alias <%= inspect @context_module %>
def index(conn, _params) do
context = build_context(conn)
items = <%= @context_short %>.<%= @list_fn %>(context)
json(conn, %{data: Enum.map(items, &serialize/1)})
end
def show(conn, %{"id" => id}) do
context = build_context(conn)
case <%= @context_short %>.<%= @get_fn %>(id, context) do
nil -> send_not_found(conn)
entity -> json(conn, %{data: serialize(entity)})
end
end
def create(conn, params) do
context = build_context(conn)
attrs = Map.get(params, "<%= @singular %>", Map.drop(params, ["id"]))
case <%= @context_short %>.<%= @create_fn %>(attrs, context) do
{:ok, entity} ->
conn |> put_status(:created) |> json(%{data: serialize(entity)})
{:error, :unauthorized} ->
send_unauthorized(conn)
{:error, %Ecto.Changeset{} = changeset} ->
send_changeset_error(conn, changeset)
{:error, reason} ->
send_error(conn, reason)
end
end
def update(conn, %{"id" => id} = params) do
context = build_context(conn)
attrs = Map.get(params, "<%= @singular %>", Map.drop(params, ["id"]))
case <%= @context_short %>.<%= @get_fn %>(id, context) do
nil ->
send_not_found(conn)
entity ->
case <%= @context_short %>.<%= @update_fn %>(entity, attrs, context) do
{:ok, updated} -> json(conn, %{data: serialize(updated)})
{:error, :unauthorized} -> send_unauthorized(conn)
{:error, %Ecto.Changeset{} = cs} -> send_changeset_error(conn, cs)
{:error, reason} -> send_error(conn, reason)
end
end
end
def delete(conn, %{"id" => id}) do
context = build_context(conn)
case <%= @context_short %>.<%= @get_fn %>(id, context) do
nil ->
send_not_found(conn)
entity ->
case <%= @context_short %>.<%= @delete_fn %>(entity, context) do
{:ok, _} -> send_resp(conn, :no_content, "")
{:error, :unauthorized} -> send_unauthorized(conn)
{:error, reason} -> send_error(conn, reason)
end
end
end
# --- Internal --------------------------------------------------------
defp build_context(conn) do
%{
current_user: conn.assigns[:current_user],
conn: conn
}
end
defp serialize(%_{} = entity) do
entity
|> Map.from_struct()
|> Map.drop([:__meta__])
|> Enum.reject(fn {_, v} -> match?(%Ecto.Association.NotLoaded{}, v) end)
|> Map.new()
end
defp send_not_found(conn),
do: conn |> put_status(:not_found) |> json(%{error: "not_found"})
defp send_unauthorized(conn),
do: conn |> put_status(:forbidden) |> json(%{error: "unauthorized"})
defp send_error(conn, reason),
do: conn |> put_status(:unprocessable_entity) |> json(%{error: inspect(reason)})
defp send_changeset_error(conn, %Ecto.Changeset{} = changeset) do
errors =
Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} ->
Enum.reduce(opts, msg, fn {k, v}, acc ->
String.replace(acc, "%{#{k}}", to_string(v))
end)
end)
conn |> put_status(:unprocessable_entity) |> json(%{errors: errors})
end
<%= @custom_marker %>