mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 13:33:20 +12:00
fix: load relationships for management properly
fix: `fetch_key` bug in embedded types fix: handle_indexed_maps for embedded types
This commit is contained in:
parent
f97caad908
commit
5425660752
3 changed files with 39 additions and 20 deletions
|
@ -5,18 +5,35 @@ defmodule Ash.Actions.ManagedRelationships do
|
|||
alias Ash.Error.Changes.InvalidRelationship
|
||||
alias Ash.Error.Query.NotFound
|
||||
|
||||
def load(_api, created, %{relationships: rels}, _) when rels == %{}, do: {:ok, created}
|
||||
def load(_api, created, %{relationships: rels}, _) when rels == %{},
|
||||
do: {:ok, created}
|
||||
|
||||
def load(_api, created, %{relationships: nil}, _), do: {:ok, created}
|
||||
|
||||
def load(api, created, changeset, opts) do
|
||||
if Ash.Changeset.ManagedRelationshipHelpers.must_load?(opts) do
|
||||
api.load(created, Map.keys(changeset.relationships),
|
||||
authorize?: opts[:authorize?],
|
||||
actor: opts[:actor]
|
||||
)
|
||||
else
|
||||
{:ok, created}
|
||||
end
|
||||
def load(api, created, changeset, engine_opts) do
|
||||
Enum.reduce_while(changeset.relationships, {:ok, created}, fn {key, value}, {:ok, acc} ->
|
||||
relationship = Ash.Resource.Info.relationship(changeset.resource, key)
|
||||
|
||||
case Enum.filter(value, fn {_, opts} ->
|
||||
opts = Ash.Changeset.ManagedRelationshipHelpers.sanitize_opts(relationship, opts)
|
||||
Ash.Changeset.ManagedRelationshipHelpers.must_load?(opts)
|
||||
end) do
|
||||
[] ->
|
||||
{:cont, {:ok, acc}}
|
||||
|
||||
relationships ->
|
||||
authorize? =
|
||||
engine_opts[:authorize?] &&
|
||||
Enum.any?(relationships, fn {_, opts} -> opts[:authorize?] end)
|
||||
|
||||
actor = engine_opts[:actor]
|
||||
|
||||
case api.load(acc, key, authorize?: authorize?, actor: actor) do
|
||||
{:ok, loaded} -> {:cont, {:ok, loaded}}
|
||||
{:error, error} -> {:halt, {:error, error}}
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def setup_managed_belongs_to_relationships(changeset, actor, engine_opts) do
|
||||
|
|
|
@ -1718,7 +1718,8 @@ defmodule Ash.Changeset do
|
|||
add_invalid_errors(:attribute, changeset, attribute, "Attribute is not writable")
|
||||
|
||||
attribute ->
|
||||
with {:ok, prepared} <-
|
||||
with value <- handle_indexed_maps(attribute.type, value),
|
||||
{:ok, prepared} <-
|
||||
prepare_change(changeset, attribute, value, attribute.constraints),
|
||||
{:ok, casted} <-
|
||||
cast_input(attribute.type, prepared, attribute.constraints, true),
|
||||
|
@ -1844,7 +1845,8 @@ defmodule Ash.Changeset do
|
|||
%{changeset | attributes: Map.put(changeset.attributes, attribute.name, nil)}
|
||||
|
||||
attribute ->
|
||||
with {:ok, prepared} <-
|
||||
with value <- handle_indexed_maps(attribute.type, value),
|
||||
{:ok, prepared} <-
|
||||
prepare_change(changeset, attribute, value, attribute.constraints),
|
||||
{:ok, casted} <-
|
||||
cast_input(attribute.type, prepared, attribute.constraints),
|
||||
|
|
|
@ -128,7 +128,7 @@ defmodule Ash.EmbeddableType do
|
|||
|
||||
defmacro single_embed_implementation do
|
||||
# credo:disable-for-next-line Credo.Check.Refactor.LongQuoteBlocks
|
||||
quote do
|
||||
quote location: :keep do
|
||||
alias __MODULE__.ShadowApi
|
||||
def storage_type, do: :map
|
||||
|
||||
|
@ -181,7 +181,7 @@ defmodule Ash.EmbeddableType do
|
|||
def fetch_key(map, atom) do
|
||||
case Map.fetch(map, atom) do
|
||||
{:ok, value} ->
|
||||
value
|
||||
{:ok, value}
|
||||
|
||||
:error ->
|
||||
Map.fetch(map, to_string(atom))
|
||||
|
@ -321,7 +321,7 @@ defmodule Ash.EmbeddableType do
|
|||
:error ->
|
||||
{pkey_field, :error}
|
||||
|
||||
value ->
|
||||
{:ok, value} ->
|
||||
attribute = Ash.Resource.Info.attribute(__MODULE__, pkey_field)
|
||||
|
||||
case Ash.Type.cast_input(attribute.type, value, attribute.constraints) do
|
||||
|
@ -362,7 +362,7 @@ defmodule Ash.EmbeddableType do
|
|||
|
||||
defmacro array_embed_implementation do
|
||||
# credo:disable-for-next-line Credo.Check.Refactor.LongQuoteBlocks
|
||||
quote do
|
||||
quote location: :keep do
|
||||
alias __MODULE__.ShadowApi
|
||||
def array_constraints, do: Ash.EmbeddableType.embedded_resource_array_constraints()
|
||||
|
||||
|
@ -482,9 +482,9 @@ defmodule Ash.EmbeddableType do
|
|||
Enum.into(pkey_fields, %{}, fn pkey_field ->
|
||||
case fetch_key(new, pkey_field) do
|
||||
:error ->
|
||||
:error
|
||||
{pkey_field, :error}
|
||||
|
||||
value ->
|
||||
{:ok, value} ->
|
||||
attr = Map.get(pkey_attributes, pkey_field)
|
||||
|
||||
case Ash.Type.cast_input(attr.type, value, attr.constraints) do
|
||||
|
@ -492,7 +492,7 @@ defmodule Ash.EmbeddableType do
|
|||
{pkey_field, casted}
|
||||
|
||||
_ ->
|
||||
:error
|
||||
{pkey_field, :error}
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
@ -538,7 +538,7 @@ defmodule Ash.EmbeddableType do
|
|||
end
|
||||
|
||||
defmacro define_embeddable_type do
|
||||
quote do
|
||||
quote location: :keep do
|
||||
use Ash.Type
|
||||
|
||||
parent = __MODULE__
|
||||
|
|
Loading…
Reference in a new issue