Alembic v4.0.0 Alembic.Error View Source
Error objects provide additional information about problems encountered
while performing an operation. Error objects MUST be returned as an array keyed by errors
in the top level of a
JSON API document.
Link to this section Summary
Types
A single error in Ecto.Changeset.t
:errors
Keyword.t
A single error field key in the Ecto.Changeset.t
:errors
Keyword.t
A single error message value in the Ecto.Changeset.t
:errors
Keyword.t
The name of a JSON type in human-readable terms, such as "array"
or "object"
Additional information about problems encountered while performing an operation
Functions
When two or more members can’t be present at the same time
Descends source
pointer
to child
of current source
pointer
Converts an Ecto.Changeset.t
error composed of the field
the error occurred on and the error message
Converts a JSON object into a JSON API Error, t
When the minimum number of children are not present, give the sender a list of the children they could have sent
When a required (MUST in the spec) member is missing
When a relationship path in "includes"
params is unknown
Fills in the format
of the error message using the values for the format keys in value_by_key
Error when the JSON type of the field is wrong
Link to this section Types
ecto_changeset_error() :: {ecto_changeset_error_field :: atom(), ecto_changeset_error_message()}
A single error in Ecto.Changeset.t
:errors
Keyword.t
A single error field key in the Ecto.Changeset.t
:errors
Keyword.t
A single error message value in the Ecto.Changeset.t
:errors
Keyword.t
.
The name of a JSON type in human-readable terms, such as "array"
or "object"
.
t() :: %Alembic.Error{ code: String.t() | nil, detail: String.t() | nil, id: String.t() | nil, links: Alembic.Links.t() | nil, meta: %{optional(String.t()) => Alembic.json() | atom()} | nil, source: Alembic.Source.t() | nil, status: String.t() | nil, title: String.t() | nil }
Additional information about problems encountered while performing an operation.
An error object MAY have the following members:
code
- an application-specific error code.detail
- a human-readable explanation specific to this occurrence of the problem.id
- a unique identifier for this particular occurrence of the problem.links
- contains the following members:"about"
- anAlembic.Link.link
leading to further details about this particular occurrence of the problem.
meta
- non-standard meta-information about the error.source
- contains references to the source of the error, optionally including any of the following members:status
- the HTTP status code applicable to this problem.title
- a short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization.
Link to this section Functions
When two or more members can’t be present at the same time.
iex> Alembic.Error.conflicting(
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/errors/0/source"
...> }
...> },
...> ~w{parameter pointer}
...> )
%Alembic.Error{
detail: "The following members conflict with each other (only one can be present):\nparameter\npointer",
meta: %{
"children" => [
"parameter",
"pointer"
]
},
source: %Alembic.Source{
pointer: "/errors/0/source"
},
status: "422",
title: "Children conflicting"
}
Descends source
pointer
to child
of current source
pointer
iex> Alembic.Error.descend(
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data"
...> }
...> },
...> 1
...> )
%Alembic.Error{
source: %Alembic.Source{
pointer: "/data/1"
}
}
from_ecto_changeset_error( ecto_changeset_error(), Alembic.Source.pointer_path_from_ecto_changeset_error_field_options() ) :: Error.t()
Converts an Ecto.Changeset.t
error composed of the field
the error occurred on and the error message
The field
is converted an Alembic.Source.t
:pointer
. If it cannot be converted, then the returned t
will have
not :source
. The child part of the :pointer
is formatted with :format_key
.
If field
is in association_set
in pointer_path_from_ecto_changeset_error_field_options
, then the pointer
will
be under /data/relationships
.
iex> format_key = fn key ->
...> key |> Atom.to_string() |> String.replace("_", "-")
...> end
iex> Alembic.Error.from_ecto_changeset_error(
...> {:favorite_posts, {"are still associated with this entry", []}},
...> %{
...> association_set: MapSet.new([:designated_editor, :favorite_posts]),
...> association_by_foreign_key: %{designated_editor_id: :designated_editor},
...> attribute_set: MapSet.new([:first_name, :last_name]),
...> format_key: format_key
...> }
...> )
%Alembic.Error{
detail: "favorite-posts are still associated with this entry",
source: %Alembic.Source{
pointer: "/data/relationships/favorite-posts"
},
title: "are still associated with this entry"
}
If field
is a key in association_by_foreign_key
in pointer_path_from_ecto_changeset_error_field_options
, then
the pointer
will be under /data/relationships
, but the child will be the name of the (formatted) association
instead of the foreign key field itself as JSONAPI attributes should not contain foreign keys.
iex> format_key = fn key ->
...> key |> Atom.to_string() |> String.replace("_", "-")
...> end
iex> Alembic.Error.from_ecto_changeset_error(
...> {:designated_editor_id, {"can't be blank", [validation: :required]}},
...> %{
...> association_set: MapSet.new([:designated_editor, :favorite_posts]),
...> association_by_foreign_key: %{designated_editor_id: :designated_editor},
...> attribute_set: MapSet.new([:first_name, :last_name]),
...> format_key: format_key
...> }
...> )
%Alembic.Error{
detail: "designated-editor can't be blank",
source: %Alembic.Source{
pointer: "/data/relationships/designated-editor"
},
title: "can't be blank"
}
If field
is in attribute_set
in pointer_path_from_ecto_changeset_error_field_options
, then the pointer
will be
under /data/attributes
.
iex> format_key = fn key ->
...> key |> Atom.to_string() |> String.replace("_", "-")
...> end
iex> Alembic.Error.from_ecto_changeset_error(
...> {:first_name, {"should be at least %{count} character(s)", [count: 2, validation: :length, min: 2]}},
...> %{
...> association_set: MapSet.new([:designated_editor, :favorite_posts]),
...> association_by_foreign_key: %{designated_editor_id: :designated_editor},
...> attribute_set: MapSet.new([:first_name, :last_name]),
...> format_key: format_key
...> }
...> )
%Alembic.Error{
detail: "first-name should be at least 2 character(s)",
source: %Alembic.Source{
pointer: "/data/attributes/first-name"
},
title: "should be at least 2 character(s)"
}
If field
is not in association_set
, attribute_set
, or a foreign key in association_by_foreign_key
in
pointer_path_from_ecto_changeset_error_field_options
, then the t
:source
will be nil
iex> format_key = fn key ->
...> key |> Atom.to_string() |> String.replace("_", "-")
...> end
iex> Alembic.Error.from_ecto_changeset_error(
...> {:favorite_flavor, {"is not allowed", []}},
...> %{
...> association_set: MapSet.new([:designated_editor, :favorite_posts]),
...> association_by_foreign_key: %{designated_editor_id: :designated_editor},
...> attribute_set: MapSet.new([:first_name, :last_name]),
...> format_key: format_key
...> }
...> )
%Alembic.Error{
detail: "favorite-flavor is not allowed",
title: "is not allowed"
}
Converts a JSON object into a JSON API Error, t
.
iex> Alembic.Error.from_json(
...> %{
...> "code" => "1",
...> "detail" => "There was an error in data",
...> "id" => "2",
...> "links" => %{
...> "about" => %{
...> "href" => "/errors/2",
...> "meta" => %{
...> "extra" => "about meta"
...> }
...> }
...> },
...> "meta" => %{
...> "extra" => "error meta"
...> },
...> "source" => %{
...> "pointer" => "/data"
...> },
...> "status" => "422",
...> "title" => "There was an error"
...> },
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/errors/0"
...> }
...> }
...> )
{
:ok,
%Alembic.Error{
code: "1",
detail: "There was an error in data",
id: "2",
links: %{
"about" => %Alembic.Link{
href: "/errors/2",
meta: %{
"extra" => "about meta"
}
}
},
meta: %{
"extra" => "error meta"
},
source: %Alembic.Source{
pointer: "/data"
},
status: "422",
title: "There was an error"
}
}
When the minimum number of children are not present, give the sender a list of the children they could have sent.
iex> Alembic.Error.minimum_children(
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data/relationships/author"
...> }
...> },
...> ~w{data links meta}
...> )
%Alembic.Error{
detail: "At least one of the following children of `/data/relationships/author` must be present:\n" <>
"data\n" <>
"links\n" <>
"meta",
meta: %{
"children" => [
"data",
"links",
"meta"
]
},
source: %Alembic.Source{
pointer: "/data/relationships/author"
},
status: "422",
title: "Not enough children"
}
When a required (MUST in the spec) member is missing
Top-level member is missing
iex> Alembic.Error.missing(
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: ""
...> }
...> },
...> "data"
...> )
%Alembic.Error{
detail: "`/data` is missing",
meta: %{
"child" => "data"
},
source: %Alembic.Source{
pointer: ""
},
status: "422",
title: "Child missing"
}
Nested member is missing
iex> Alembic.Error.missing(
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data"
...> }
...> },
...> "type"
...> )
%Alembic.Error{
detail: "`/data/type` is missing",
meta: %{
"child" => "type"
},
source: %Alembic.Source{
pointer: "/data"
},
status: "422",
title: "Child missing"
}
When a relationship path in "includes"
params is unknown.
If no template is given, it is assumed that the source is the “include” parameter
iex> Alembic.Error.relationship_path("secret")
%Alembic.Error{
detail: "`secret` is an unknown relationship path",
meta: %{
"relationship_path" => "secret"
},
source: %Alembic.Source{
parameter: "include"
},
title: "Unknown relationship path"
}
If using a different parameter than recommended in the JSON API spec, a template can be used
iex> Alembic.Error.relationship_path(
...> %Alembic.Error{
...> source: %Alembic.Source{
...> parameter: "relationships"
...> }
...> },
...> "secret"
...> )
%Alembic.Error{
detail: "`secret` is an unknown relationship path",
meta: %{
"relationship_path" => "secret"
},
source: %Alembic.Source{
parameter: "relationships"
},
title: "Unknown relationship path"
}
title_from_ecto_changeset_error_message(ecto_changeset_error_message()) :: String.t()
Fills in the format
of the error message using the values for the format keys in value_by_key
Error when the JSON type of the field is wrong.
NOTE: The JSON type should be used, not the Elixir/Erlang type, so if a member is not a map
in Elixir, the
human_type
should be "object"
. Likewise, if a member is not a list
in Elixir, the human_type
should be
"array"
.
When member is not an Elixir list
or JSON array
iex> validate_errors = fn
...> (list) when is_list(list) ->
...> {:ok, list}
...> (_) ->
...> {
...> :error,
...> Alembic.Error.type(
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/errors"
...> }
...> },
...> "array"
...> )
...> }
...> end
iex> json = %{"errors" => "invalid"}
iex> validate_errors.(json["errors"])
{
:error,
%Alembic.Error{
detail: "`/errors` type is not array",
meta: %{
"type" => "array"
},
source: %Alembic.Source{
pointer: "/errors"
},
status: "422",
title: "Type is wrong"
}
}
When member is not an Elixir map
or JSON object
iex> validate_meta = fn
...> (meta) when is_map(meta) ->
...> {:ok, meta}
...> (_) ->
...> {
...> :error,
...> Alembic.Error.type(
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/meta"
...> }
...> },
...> "object"
...> )
...> }
...> end
iex> json = %{"meta" => "invalid"}
iex> validate_meta.(json["meta"])
{
:error,
%Alembic.Error{
detail: "`/meta` type is not object",
meta: %{
"type" => "object"
},
source: %Alembic.Source{
pointer: "/meta"
},
status: "422",
title: "Type is wrong"
}
}