# `MonEx.Ecto`
[🔗](https://github.com/youroff/monex/blob/v0.2.1/lib/monex/ecto.ex#L1)

Ecto extensions for MonEx.

`use MonEx.Ecto` inside an `Ecto.Repo` to add Option-returning lookups
and a Multi result repacker. Requires the consumer app to depend on
`:ecto`.

## Usage

    defmodule MyApp.Repo do
      use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres
      use MonEx.Ecto
    end

This injects `one_option/2`, `get_option/3`, and `get_by_option/3` into
the host Repo and exposes `repack_multi/1,2`. The `*_option` helpers
wrap the standard `nil`-returning Repo callbacks into `MonEx.Option`:

    MyApp.Repo.get_option(User, user_id)
    |> map(&do_something/1)
    |> get_or_else(default_user())

`repack_multi/2` normalises the outcome of `Repo.transaction/1` on an
`Ecto.Multi` into a `MonEx.Result`, handling both the success shape
(`{:ok, changes}`) and the failure shape
(`{:error, operation, value, changes_so_far}`).

# `repack_multi`

```elixir
@spec repack_multi(
  {:ok, map()}
  | {:error, Ecto.Multi.name(), any(), %{required(Ecto.Multi.name()) =&gt; any()}},
  Keyword.t()
) :: MonEx.Result.t(any(), any())
```

Repacks the result of `Repo.transaction/1` on an `Ecto.Multi` into a
`MonEx.Result`.

On success, the changes map is normalised: entries shaped as
`{value, ret}` tuples (the convention used by `Ecto.Multi.run/3`
callbacks) are unwrapped to either `value` or `ret` depending on
whether `ret` is `nil`.

## Options

  * `:error` — what to surface when the Multi failed:
    * `:all` (default) — `{operation, value, changes_so_far}` tuple
    * `:operation` — just the failed operation's name
    * `:value` — just the failed operation's value (e.g. a changeset)
    * `:changes` — just the changes accumulated before the failure

  * `:result` — what to surface on success:
    * `:all` (default) — the full normalised changes map
    * an operation name — just that operation's value, looked up in
      the changes map (returns `ok(nil)` if absent)

## Examples
    iex> MonEx.Ecto.repack_multi({:ok, %{a: 1, b: 2}})
    {:ok, %{a: 1, b: 2}}

    iex> MonEx.Ecto.repack_multi({:ok, %{a: 1, b: 2}}, result: :a)
    {:ok, 1}

    iex> MonEx.Ecto.repack_multi({:error, :step, :boom, %{}})
    {:error, {:step, :boom, %{}}}

    iex> MonEx.Ecto.repack_multi({:error, :step, :boom, %{}}, error: :value)
    {:error, :boom}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
