BoxTurtle.Common.ReturnOkOr (BoxTurtle v0.1.0)

Copy Markdown View Source

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}

Summary

Functions

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

Wraps reason in an error tuple.

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

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).

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

Functions

error_with_stack(message)

(macro)

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

return_error(reason)

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

Wraps reason in an error tuple.

return_ok_or(ok)

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

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

return_ok_or(ok, reason)

@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(message)

(macro)

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