After 'mix phx.gen.json Items Item items name:string description:string info:string amount:integer factor:float type:string --no-context --no-schema'.

This commit is contained in:
2026-04-21 13:56:18 +02:00
parent 851665ef60
commit 6076654aa4
6 changed files with 224 additions and 3 deletions

View File

@ -0,0 +1,25 @@
defmodule GenericRestServerWeb.ChangesetJSON do
@doc """
Renders changeset errors.
"""
def error(%{changeset: changeset}) do
# When encoded, the changeset returns its errors
# as a JSON object. So we just pass it forward.
%{errors: Ecto.Changeset.traverse_errors(changeset, &translate_error/1)}
end
defp translate_error({msg, opts}) do
# You can make use of gettext to translate error messages by
# uncommenting and adjusting the following code:
# if count = opts[:count] do
# Gettext.dngettext(GenericRestServerWeb.Gettext, "errors", msg, msg, count, opts)
# else
# Gettext.dgettext(GenericRestServerWeb.Gettext, "errors", msg, opts)
# end
Enum.reduce(opts, msg, fn {key, value}, acc ->
String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end)
end)
end
end

View File

@ -0,0 +1,16 @@
defmodule GenericRestServerWeb.FallbackController do
@moduledoc """
Translates controller action results into valid `Plug.Conn` responses.
See `Phoenix.Controller.action_fallback/1` for more details.
"""
use GenericRestServerWeb, :controller
# This clause is an example of how to handle resources that cannot be found.
def call(conn, {:error, :not_found}) do
conn
|> put_status(:not_found)
|> put_view(html: GenericRestServerWeb.ErrorHTML, json: GenericRestServerWeb.ErrorJSON)
|> render(:"404")
end
end

View File

@ -0,0 +1,43 @@
defmodule GenericRestServerWeb.ItemController do
use GenericRestServerWeb, :controller
alias GenericRestServer.Items
alias GenericRestServer.Items.Item
action_fallback GenericRestServerWeb.FallbackController
def index(conn, _params) do
items = Items.list_items(conn.assigns.current_scope)
render(conn, :index, items: items)
end
def create(conn, %{"item" => item_params}) do
with {:ok, %Item{} = item} <- Items.create_item(conn.assigns.current_scope, item_params) do
conn
|> put_status(:created)
|> put_resp_header("location", ~p"/api/items/#{item}")
|> render(:show, item: item)
end
end
def show(conn, %{"id" => id}) do
item = Items.get_item!(conn.assigns.current_scope, id)
render(conn, :show, item: item)
end
def update(conn, %{"id" => id, "item" => item_params}) do
item = Items.get_item!(conn.assigns.current_scope, id)
with {:ok, %Item{} = item} <- Items.update_item(conn.assigns.current_scope, item, item_params) do
render(conn, :show, item: item)
end
end
def delete(conn, %{"id" => id}) do
item = Items.get_item!(conn.assigns.current_scope, id)
with {:ok, %Item{}} <- Items.delete_item(conn.assigns.current_scope, item) do
send_resp(conn, :no_content, "")
end
end
end

View File

@ -0,0 +1,29 @@
defmodule GenericRestServerWeb.ItemJSON do
alias GenericRestServer.Items.Item
@doc """
Renders a list of items.
"""
def index(%{items: items}) do
%{data: for(item <- items, do: data(item))}
end
@doc """
Renders a single item.
"""
def show(%{item: item}) do
%{data: data(item)}
end
defp data(%Item{} = item) do
%{
id: item.id,
name: item.name,
description: item.description,
info: item.info,
amount: item.amount,
factor: item.factor,
type: item.type
}
end
end

View File

@ -24,9 +24,11 @@ defmodule GenericRestServerWeb.Router do
end
# Other scopes may use custom stacks.
# scope "/api", GenericRestServerWeb do
# pipe_through :api
# end
scope "/api", GenericRestServerWeb do
pipe_through :api
resources "/items", ItemController, except: [:new, :edit]
end
# Enable LiveDashboard and Swoosh mailbox preview in development
if Application.compile_env(:generic_rest_server, :dev_routes) do

View File

@ -0,0 +1,106 @@
defmodule GenericRestServerWeb.ItemControllerTest do
use GenericRestServerWeb.ConnCase
import GenericRestServer.ItemsFixtures
alias GenericRestServer.Items.Item
@create_attrs %{
info: "some info",
name: "some name",
type: "some type",
description: "some description",
amount: 42,
factor: 120.5
}
@update_attrs %{
info: "some updated info",
name: "some updated name",
type: "some updated type",
description: "some updated description",
amount: 43,
factor: 456.7
}
@invalid_attrs %{info: nil, name: nil, type: nil, description: nil, amount: nil, factor: nil}
setup :register_and_log_in_user
setup %{conn: conn} do
{:ok, conn: put_req_header(conn, "accept", "application/json")}
end
describe "index" do
test "lists all items", %{conn: conn} do
conn = get(conn, ~p"/api/items")
assert json_response(conn, 200)["data"] == []
end
end
describe "create item" do
test "renders item when data is valid", %{conn: conn} do
conn = post(conn, ~p"/api/items", item: @create_attrs)
assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get(conn, ~p"/api/items/#{id}")
assert %{
"id" => ^id,
"amount" => 42,
"description" => "some description",
"factor" => 120.5,
"info" => "some info",
"name" => "some name",
"type" => "some type"
} = json_response(conn, 200)["data"]
end
test "renders errors when data is invalid", %{conn: conn} do
conn = post(conn, ~p"/api/items", item: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{}
end
end
describe "update item" do
setup [:create_item]
test "renders item when data is valid", %{conn: conn, item: %Item{id: id} = item} do
conn = put(conn, ~p"/api/items/#{item}", item: @update_attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get(conn, ~p"/api/items/#{id}")
assert %{
"id" => ^id,
"amount" => 43,
"description" => "some updated description",
"factor" => 456.7,
"info" => "some updated info",
"name" => "some updated name",
"type" => "some updated type"
} = json_response(conn, 200)["data"]
end
test "renders errors when data is invalid", %{conn: conn, item: item} do
conn = put(conn, ~p"/api/items/#{item}", item: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{}
end
end
describe "delete item" do
setup [:create_item]
test "deletes chosen item", %{conn: conn, item: item} do
conn = delete(conn, ~p"/api/items/#{item}")
assert response(conn, 204)
assert_error_sent 404, fn ->
get(conn, ~p"/api/items/#{item}")
end
end
end
defp create_item(%{scope: scope}) do
item = item_fixture(scope)
%{item: item}
end
end