# `BoxTurtle.Common.ReturnOkOr`
[🔗](https://github.com/twajjo/box_turtle/blob/v0.1.0/lib/common/return_ok_or.ex#L1)

Normalizes loosely-shaped results (`nil`, bare values, `:error`, `{:error, _}`) into `{:ok, value}` /
`{:error, reason}` tuples, plus macros that log a message together with the caller's stack trace.

    defmodule MyApp.Blog do
      import BoxTurtle.Common.ReturnOkOr

      alias MyApp.Blog.Post
      alias MyApp.Repo

      # Repo.get/2 returns a struct or nil; callers get {:ok, post} or {:error, :not_found}.
      def fetch_post(id), do: Post |> Repo.get(id) |> return_ok_or(:not_found)

      # Map.fetch/2 returns {:ok, value} or :error; normalize :error to a reason.
      def fetch_setting(settings, key), do: settings |> Map.fetch(key) |> return_ok_or(:missing_setting)

      def publish(id) do
        with {:ok, post} <- fetch_post(id) do
          post |> Post.changeset(%{status: "published"}) |> Repo.update()
        end
      end
    end

    MyApp.Blog.fetch_post(42)                       #=> {:ok, %MyApp.Blog.Post{id: 42}}
    MyApp.Blog.fetch_post(-1)                       #=> {:error, :not_found}
    MyApp.Blog.fetch_setting(%{theme: "dark"}, :lang) #=> {:error, :missing_setting}

# `error_with_stack`
*macro* 

Logs `message` at `:error` level with the current stack trace. A macro, so the trace starts at the caller.

# `return_error`

```elixir
@spec return_error(reason) :: {:error, reason} when reason: term()
```

Wraps `reason` in an error tuple.

# `return_ok_or`

```elixir
@spec return_ok_or({:ok, term()} | {:error, term()} | :error) ::
  {:ok, term()} | {:error, term()} | :error
```

Passes `{:ok, _}`, `{:error, _}` and `:error` through unchanged.

# `return_ok_or`

```elixir
@spec return_ok_or(term(), reason) :: {:ok, term()} | {:error, reason}
when reason: term()
```

Returns `{:ok, value}` for a value or an `{:ok, _}` tuple, and `{:error, reason}` for `nil`, `:error` or an
`{:error, _}` tuple (whose own reason is replaced by `reason`).

# `warn_with_stack`
*macro* 

Logs `message` at `:warning` level with the current stack trace. A macro, so the trace starts at the caller.

---

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