Alembic v4.0.0 Alembic.ResourceIdentifier View Source
Link to this section Summary
Types
A “resource identifier object” is [an
%Alembic.ResourceIdentifier{}
] that identifies an individual resource.A “resource identifier object” MUST contain
type
andid
members.A “resource identifier object” MAY also include a
meta
member, whose value is a [Alembic.Meta.t
] that contains non-standard meta-information.— JSON API - Document Structure - Resource Identifier Object
Functions
Examples
Converts resource_identifier
to params format used by
Ecto.Changeset.cast/4
Unlike to_params/2
, if type
and id
of convertable
already exists in converted_by_id_by_type
, then the params
returned are only %{ "id" => id }
without any further expansion, that is, a resource identifier, so that loops are
prevented
Link to this section Types
t() :: %Alembic.ResourceIdentifier{ id: String.t(), meta: Alembic.Meta.t(), type: String.t() }
A “resource identifier object” is [an
%Alembic.ResourceIdentifier{}
] that identifies an individual resource.A “resource identifier object” MUST contain
type
andid
members.A “resource identifier object” MAY also include a
meta
member, whose value is a [Alembic.Meta.t
] that contains non-standard meta-information.— JSON API - Document Structure - Resource Identifier Object
Link to this section Functions
from_json( %{optional(String.t()) => String.t() | Alembic.json_object()}, Alembic.Error.t() ) :: {:ok, t()} | Alembic.FromJson.error()
from_json( nil | true | false | list() | float() | integer() | String.t(), Alembic.Error.t() ) :: Alembic.FromJson.error()
Examples
A resource identifier is valid with "id"
and "type"
iex> Alembic.ResourceIdentifier.from_json(
...> %{"id" => "1", "type" => "shirt"},
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data/relationships/shirt/data"
...> }
...> }
...> )
{:ok, %Alembic.ResourceIdentifier{id: "1", type: "shirt"}}
A resource identifier can optionally have "meta"
iex> Alembic.ResourceIdentifier.from_json(
...> %{"id" => "1", "meta" => %{"copyright" => "2015"}, "type" => "shirt"},
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data/relationships/shirt/data"
...> }
...> }
...> )
{:ok, %Alembic.ResourceIdentifier{id: "1", meta: %{"copyright" => "2015"}, type: "shirt"}}
A resource identifier MUST have an "id"
iex> Alembic.ResourceIdentifier.from_json(
...> %{"type" => "shirt"},
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data/relationships/shirt/data"
...> }
...> }
...> )
{
:error,
%Alembic.Document{
errors: [
%Alembic.Error{
detail: "`/data/relationships/shirt/data/id` is missing",
meta: %{
"child" => "id"
},
source: %Alembic.Source{
pointer: "/data/relationships/shirt/data"
},
status: "422",
title: "Child missing"
}
]
}
}
A resource identifer MUST have a "type"
iex> Alembic.ResourceIdentifier.from_json(
...> %{"id" => "1"},
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data/relationships/shirt/data"
...> }
...> }
...> )
{
:error,
%Alembic.Document{
errors: [
%Alembic.Error{
detail: "`/data/relationships/shirt/data/type` is missing",
meta: %{
"child" => "type"
},
source: %Alembic.Source{
pointer: "/data/relationships/shirt/data"
},
status: "422",
title: "Child missing"
}
]
}
}
A resource identifer missing both "id"
and "type"
will show both as missing
iex> Alembic.ResourceIdentifier.from_json(
...> %{},
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data/relationships/shirt/data"
...> }
...> }
...> )
{
:error,
%Alembic.Document{
errors: [
%Alembic.Error{
detail: "`/data/relationships/shirt/data/id` is missing",
meta: %{
"child" => "id"
},
source: %Alembic.Source{
pointer: "/data/relationships/shirt/data"
},
status: "422",
title: "Child missing"
},
%Alembic.Error{
detail: "`/data/relationships/shirt/data/type` is missing",
meta: %{
"child" => "type"
},
source: %Alembic.Source{
pointer: "/data/relationships/shirt/data"
},
status: "422",
title: "Child missing"
}
]
}
}
A non-resource-identifier will be identified as such
iex> Alembic.ResourceIdentifier.from_json(
...> [],
...> %Alembic.Error{
...> source: %Alembic.Source{
...> pointer: "/data/relationships/shirt/data"
...> }
...> }
...> )
{
:error,
%Alembic.Document{
errors: [
%Alembic.Error{
detail: "`/data/relationships/shirt/data` type is not resource identifier",
meta: %{
"type" => "resource identifier"
},
source: %Alembic.Source{
pointer: "/data/relationships/shirt/data"
},
status: "422",
title: "Type is wrong"
}
]
}
}
to_params(t(), Alembic.ToParams.resource_by_id_by_type()) :: Alembic.ToParams.params()
Converts resource_identifier
to params format used by
Ecto.Changeset.cast/4
.
id
and type
will be used to lookup the attributes in resource_by_id_by_type
. Theses attributes and the id
will be combined into a map for params
iex> Alembic.ResourceIdentifier.to_params(
...> %Alembic.ResourceIdentifier{id: "1", type: "author"},
...> %{
...> "author" => %{
...> "1" => %Alembic.Resource{
...> type: "author",
...> id: "1",
...> attributes: %{
...> "name" => "Alice"
...> }
...> }
...> }
...> }
...> )
%{
"id" => "1",
"name" => "Alice"
}
If no entry is found in resource_by_id_by_type
, then only the id
is copied to the params. This can happen when
the server only wants to send foreign keys.
iex> Alembic.ResourceIdentifier.to_params(
...> %Alembic.ResourceIdentifier{id: "1", type: "author"},
...> %{}
...> )
%{
"id" => "1"
}
to_params( t(), Alembic.ToParams.resource_by_id_by_type(), Alembic.ToParams.converted_by_id_by_type() ) :: Alembic.ToParams.params()
Unlike to_params/2
, if type
and id
of convertable
already exists in converted_by_id_by_type
, then the params
returned are only %{ "id" => id }
without any further expansion, that is, a resource identifier, so that loops are
prevented.
Parameters
convertable
- anAlembic.Document.t
hierarchy data structureresources_by_id_by_type
- A nest map with the outer layer keyed by theAlembic.Resource.type
, then the next layer keyed by theAlembic.Resource.id
with the values being the fullAlembic.Resource.t
fromAlembic.Document.t
included
.converted_by_id_by_type
- Tracks which (type, id) have been converted already to prevent infinite recursion when expanding indirect relationships.
Returns
Success
{nil}
if an empty singleton%{}
- if a non-empty singleton[]
- if an empty collection[%{}]
- if a non-empty collection
Errors
{:error, :already_converted}
- if thetype
andid
ofconvertable
already exists inconverted_by_id_by_type
{:error, :unset}
- if theconvertable
data is not set
Callback implementation for Alembic.ToParams.to_params/3
.