harnais_error v0.3.0 Harnais.Error exception View Source
The Exception for the Harnais Package Family.
Many of the functions in the Harnais packages return
either {:ok, any}
or {error, error}
where error
will be an
Exception
.
Many of the errors will be instances of Harnais.Error
struct
.
Exporting the Exception
As well as supporting the usual Exception
callbacks, the package
support “exporting” the exception using Harnais.Error.export/1
.
See the exception fields :export_function
and :export_config
for
how to contol what the export does.
Exception State
The exception struct
has a number of fields
Field | Aliases |
---|---|
:message | :m, :msg |
:reason | :r |
:type | :t |
:location | :l, :loc, :ndx, :index, :i |
:value0 | :v, :v0, :value, :e, :error |
:value1 | :v1 |
:value2 | :v2 |
:message_function | |
:message_config | |
:export_function | |
:export_config |
Exception Field: :message
The explanatory message, normally a string.
Exception Field: :reason
The reason for the error; normally an Atom
.
Exception Field: :type
An aribtrary term defining the type of the error e.g. :arg
, :key
, :value
, etc
Exception Field: :location
An aribtrary term defining where the error happened.
For example this could be a key, index in a list, whatever.
Exception Field: :value0
, :value1
, :value2
Arbitrary terms identifying the cause of the error.
Three fields are useful when, for example, :value0
holds the name of
a key and :value1
and :value2
hold the values of the key that
were expected to be equal.
Sometimes :value0
holds an instance of Harnais.Error.Status
.
Exception Field: :message_function
The module implements its own Exception.message/1
callback but
this can be overridden by this field.
If supplied, it must be an arity 1 function that is passed the
struct
and must return a string.
Exception Field: :message_config
This field is used by the default Exception.message/1
formatter to
hold the fields to be included in the message. It can be overridden
to set the wanted fields.
If an explicit :message_function
function is supplied, this field
can also be used to hold configuration for it.
Exception Field: :export_function
The exception can be “exported” using Harnais.Error.export/1
which
is passed the exception struct.
The default exporter creates a Keyword
of selected fields where
the keys are the shortest alias for the field (e.g. :m
for
:message
).
A custom export function can be provided using this field.
Exception Field: :export_config
The default exporter using this field to hold the fields to be included in the export.
If a custom export function is provided, this field can be used to provide configuration for it.
Standard API
Unless otherwise specified, functions return either {:ok, status}
or {:error, error}
when error
will be an Exception..
Many functions have peer bang functions that returns either the value
in {:ok, value}
or raise the error
in {:error, error}
.
Link to this section Summary
Functions
Callback implementation for Exception.exception/1
export/2
takes an instance of the module’s struct
and an optional opts and exports it
export_exception/1
takes an exception struct and optional opts and exports it
gather_export/1
takes an export and, if the export is a Keyword
or list of
Keyword
, gathers all the values for the same key
(Keyword.get_values/2
) together
new/1
creates an instance of the error module’s struct t
update/2
takes an instance
of the module’s struct
and an optional opts
Link to this section Types
Link to this section Functions
Callback implementation for Exception.exception/1
.
export/2
takes an instance of the module’s struct
and an optional opts and exports it.
If the opts are not empty, update/2
is called with the struct
and opts
before performing the export.
A custom arity one export function can be given in the field :export_function
.
Otherwise the default export function is used which creates Keyword
with one key (:error
) whose value is a list of Keyword
s of the set fields in the
error where the keys are the short form of the full field name (e.g. :m
for :message
)
If the export works, {:ok, export}
is returned.
Examples
iex> {:ok, error} = [message: "something broke", type: :arg, value: 42] |> new
...> error |> export
{:ok, [error: [[m: "something broke", t: :arg, v: 42]]]}
iex> export_fun = fn error -> {:ok, error.value} end
...> {:ok, error} = [export_function: export_fun, message: "something broke", type: :arg, value: 42] |> new
...> error |> export
{:ok, 42}
In these two examples :export_config
is given in the opts to
change the fields in the export. The second example show the error
when an unknown field is given.
iex> {:ok, error} = [message: "something broke", type: :arg, value: 42] |> new
...> error |> export(export_config: [:m, :v])
{:ok, [error: [[m: "something broke", v: 42]]]}
iex> {:ok, error} = [message: "something broke", type: :arg, value: 42] |> new
...> {:error, export_error} = error |> export(export_config: [:m, :unknown_key])
...> export_error |> Exception.message |> String.starts_with?("key :unknown_key not found")
true
export_exception/1
takes an exception struct and optional opts and exports it.
If the struct is a Harnais.Error
or Harnais.Error.Status
their respective export/2
functions are called.
For any other exception, Exception.message/1
is called and {:ok, [m: message]}
returned.
Examples
iex> {:ok, error} = [message: "something broke", type: :arg, value: 42] |> new
...> error |> export_exception
{:ok, [error: [[m: "something broke", t: :arg, v: 42]]]}
iex> {:ok, error} = [add_results: [ok: 42, error: :got_an_error, error: %BadMapError{term: 42}]]
...> |> Harnais.Error.Status.new
...> error |> export_exception
{:ok, [ok: 42, error: [[v: :got_an_error]], error: [[m: "expected a map, got: 42"]]]}
iex> %RuntimeError{message: "this is a test"} |> export_exception
{:ok, [error: [[m: "this is a test"]]]}
iex> %KeyError{key: :b, term: %{a: 1}} |> export_exception
{:ok, [error: [[m: "key :b not found in: %{a: 1}"]]]}
gather_export/1
takes an export and, if the export is a Keyword
or list of
Keyword
, gathers all the values for the same key
(Keyword.get_values/2
) together.
The argument is expected to be the export
in {:ok, export}
returned by export/2
or export_exception/2
.
Otherwise the export is returned unchanged as {:ok, export}
.
Examples
Gathering the export of single exception may not make any differnce:
iex> {:ok, error} = [message: "something broke", type: :arg, value: 42] |> new
...> {:ok, export} = error |> export_exception
...> export |> gather_export
{:ok, [error: [[m: "something broke", t: :arg, v: 42]]]}
iex> {:ok, export} = %KeyError{key: :b, term: %{a: 1}} |> export_exception
...> export |> gather_export
{:ok, [error: [[m: "key :b not found in: %{a: 1}"]]]}
However, when there are multiple :ok
and/or :error
values, they will be gathered together.
iex> {:ok, error} = [add_results:
...> [ok: 42, error: :got_an_error, error: %BadMapError{term: 42}, ok: "Hello World"]
...> ] |> Harnais.Error.Status.new
...> {:ok, export} = error |> export_exception
...> export |> gather_export
{:ok, [ok: [42, "Hello World"], error: [[v: :got_an_error], [m: "expected a map, got: 42"]]]}
new/1
creates an instance of the error module’s struct t
.
If the opts
are not empty, it calls update/2
with t
and the opts
.
Either {:ok, t}
or {:error, error}
is returned where error
is
an exception generated during the creation.
Examples
iex> {:ok, t} = new()
...> match?(%Harnais.Error{}, t)
true
iex> {:ok, t} = new(m: "failed again", r: :usual_cause, v: 42)
...> t |> Exception.message
"failed again, reason=:usual_cause, got: 42"
update/2
takes an instance
of the module’s struct
and an optional opts.
The opts are normalised by calling the module’s update_canonical_opts/1
and then reduced with update_field/2
:
opts |> Enum.reduce(instance, fn {k,v}, s -> s |> update_field({k,v}) end)
{:ok, instance}
is returned.