Current section

Files

Jump to
formex lib formex controller.ex
Raw

lib/formex/controller.ex

defmodule Formex.Controller do
alias Formex.Form
@repo Application.get_env(:formex, :repo)
defmacro __using__(_) do
quote do
import Formex.Builder
import Formex.Controller
end
end
@moduledoc """
Helpers for controller. Imports `Formex.Builder`.
# Installation:
`web/web.ex`
```
def controller do
quote do
use Formex.Controller
end
end
```
# Usage
## CRUD
```
def new(conn, _params) do
form = create_form(App.ArticleType, %Article{})
render(conn, "new.html", form: form)
end
```
```
def create(conn, %{"article" => article_params}) do
App.ArticleType
|> create_form(%Article{}, article_params)
|> insert_form_data
|> case do
{:ok, _article} ->
# ...
{:error, form} ->
# ...
end
end
```
```
def edit(conn, %{"id" => id}) do
article = Repo.get!(Article, id)
form = create_form(App.ArticleType, article)
render(conn, "edit.html", article: article, form: form)
end
```
```
def update(conn, %{"id" => id, "article" => article_params}) do
article = Repo.get!(Article, id)
App.ArticleType
|> create_form(article, article_params)
|> update_form_data
|> case do
{:ok, article} ->
# ...
{:error, form} ->
# ...
end
end
```
## Usage without a database
```
defmodule App.Registration do
use App.Web, :model
embedded_schema do # instead of `schema`
field :email
field :password
end
end
```
```
def register(conn, %{"registration" => registration_params}) do
RegistrationType
|> create_form(%Registration{}, registration_params)
|> handle_form
|> case do
{:ok, registration} ->
# do something with the `registration`
{:error, form} ->
# display errors
render(conn, "index.html", form: form)
end
end
```
"""
@doc """
Works similar to `insert_form_data/1` and `update_form_data/1`, but doesn't require a database.
Should be used with `embedded_schema`.
"""
@spec handle_form(Form.t) :: {:ok, Ecto.Schema.t} | {:error, Form.t}
def handle_form(form) do
if form.changeset.valid? do
{:ok, Ecto.Changeset.apply_changes(form.changeset)}
else
changeset = %{form.changeset | action: :update}
{:error, Map.put(form, :changeset, changeset)}
end
end
@doc """
Invokes `Repo.insert`. In case of `:error`, returns `{:error, form}` (with new `form.changeset`
value) instead of `{:error, changeset}` (as Ecto does)
"""
@spec insert_form_data(Form.t) :: {:ok, Ecto.Schema.t} | {:error, Form.t}
def insert_form_data(form) do
case @repo.insert(form.changeset) do
{:ok, schema} -> {:ok, schema}
{:error, changeset} -> {:error, Map.put(form, :changeset, changeset)}
end
end
@doc """
Invokes `Repo.update`. In case of `:error`, returns `{:error, form}` (with new `form.changeset`
value) instead of `{:error, changeset}` (as Ecto does)
"""
@spec update_form_data(Form.t) :: {:ok, Ecto.Schema.t} | {:error, Form.t}
def update_form_data(form) do
case @repo.update(form.changeset) do
{:ok, schema} -> {:ok, schema}
{:error, changeset} -> {:error, Map.put(form, :changeset, changeset)}
end
end
end