Transponder
DRY up your Phoenix controllers.
Features
- Turns controllers into declarative code.
- Works with any context function that returns a tagged tuple like
{:ok, ...}or{:error, ...} - Understands
Ecto.Changeseterrors and can render the error. - Built in responders for JSON and HTML and ability to create custom ones.
Disclaimer: this is intended for simple apps or for when you're just starting out building an app. More complex apps will require more code in their controllers and should use standard Phoenix controllers and tests. This is just a starting point.
Installation
Add transponder to your list of dependencies in mix.exs:
def deps do
[
{:transponder, "~> 0.1.0"}
]
end
Add use Transponder to your controllers, and define actions with defaction:
defmodule MyAppWeb.Admin.ProductsController do
use MyAppWeb, :controller
use Transponder,
responder: Transponder.Responders.JSON
defaction :index, &Catalog.list_products(&1.params)
defaction :show, &Catalog.get_product(&1.params)
defaction :create, &Catalog.create_product(&1.params["product"])
defaction :update, &Catalog.update_product(&1.params["id"], &1.params["product"])
defaction :delete, &Catalog.delete_product(&1.params["id"])
end
Then define a show.json.eex and index.json.eex. Or you can use a Phoenix.View:
defmodule MyAppWeb.Admin.ProductsView do
use MyAppWeb, :view
def render("index.json", %{response: products}) do
%{products: Enum.map(&render("show.json", response: &1))}
end
def render("show.json", %{response: product}) do
%{
id: product.id,
title: product.title,
price: product.price,
}
end
end
To render HTML instead of JSON use Responders.HTML:
defmodule MayAppWeb.Admin.ProductController do
use MyAppWeb, :controller
use Transponder,
responder: Transponder.Responders.HTML
# defaction ...
end
And then you'll need to create templates for the actions you use: index.html.eex, show.html.eex, etc..
You can also create a custom responder:
defmodule MyResponder do
@behaviour Transponder.Responder
# pattern match and render how you like
@impl true
def respond(_action, conn, {:ok, bla}) do
conn
|> put_status(200)
|> render("yay.html")
end
def respond(_action, conn, {:error, bla}) do
conn
|> put_status(401)
|> render("oops.html")
end
end
Documentation:
https://hexdocs.pm/transponder.
License
MIT