Transponder

DRY up your Phoenix controllers.

Features

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