Current section
Files
Jump to
Current section
Files
lib/controller.ex
defmodule Formex.Ecto.Controller do
alias Formex.Form
alias Formex.Builder
import Formex.Ecto.Changeset
@repo Application.get_env(:formex, :repo)
defmacro __using__(_) do
quote do
import Formex.Ecto.Controller
end
end
@moduledoc """
Ecto helpers for controller.
# Installation:
`web/web.ex`
```
def controller do
quote do
use Formex.Ecto.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
```
"""
@doc """
Works same as `Formex.Controller.handle_form/2`, but also invokes `Ecto.Repo.insert/2`
"""
@spec insert_form_data(Form.t) :: {:ok, Ecto.Schema.t} | {:error, Form.t}
def insert_form_data(form) do
form = Builder.handle_submit(form)
if form.valid? do
form
|> create_changeset
|> @repo.insert
|> case do
{:error, changeset} ->
raise_changeset_error(form, changeset)
{:ok, struct} -> {:ok, struct}
end
else
{:error, %{form | submitted?: true}}
end
end
@doc """
Works same as `Formex.Controller.handle_form/2`, but also invokes `Ecto.Repo.update/2`
"""
@spec update_form_data(Form.t) :: {:ok, Ecto.Schema.t} | {:error, Form.t}
def update_form_data(form) do
form = Builder.handle_submit(form)
if form.valid? do
form
|> create_changeset
|> @repo.update
|> case do
{:error, changeset} ->
raise_changeset_error(form, changeset)
{:ok, struct} -> {:ok, struct}
end
else
{:error, %{form | submitted?: true}}
end
end
defp raise_changeset_error(form, changeset) do
errors = Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} ->
Enum.reduce(opts, msg, fn {key, value}, acc ->
String.replace(acc, "%{#{key}}", to_string(value))
end)
end)
if errors != %{} do
raise "Your changeset has errors. Since Formex 0.5, errors added in
`Type.changeset_after_create_callback` are not being validated. You have to use
new validator functionality. Errors found:\n
"<>inspect(errors)
end
{:error, %{form | submitted?: true}}
end
end