From 80833c3f58b649bae7fa95353f5c477680b21ae5 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Mon, 22 Aug 2022 19:48:22 -0400 Subject: [PATCH] improvement: handle the case where managed relationship input is an embed --- lib/ash/actions/managed_relationships.ex | 67 +++++++++++++++++------- priv/documentation/how_to/upgrading.md | 6 ++- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/lib/ash/actions/managed_relationships.ex b/lib/ash/actions/managed_relationships.ex index 1b98b61d..fcdefc66 100644 --- a/lib/ash/actions/managed_relationships.ex +++ b/lib/ash/actions/managed_relationships.ex @@ -166,7 +166,7 @@ defmodule Ash.Actions.ManagedRelationships do ) {_key, _create_or_update, read} -> - if is_struct(input) do + if is_struct(input, relationship.destination) do changeset = changeset |> Ash.Changeset.set_context(%{ @@ -839,7 +839,7 @@ defmodule Ash.Actions.ManagedRelationships do case Ash.Filter.get_filter(relationship.destination, input) do {:ok, keys} -> - if is_struct(input) do + if is_struct(input, relationship.destination) do {:ok, input} else relationship.destination @@ -986,10 +986,15 @@ defmodule Ash.Actions.ManagedRelationships do type when type in [:has_many, :has_one] -> {found, input} = - if is_struct(input) do - {input, %{}} - else - {found, input} + cond do + is_struct(input, relationship.destination) -> + {input, %{}} + + is_struct(input) -> + {found, Map.from_struct(input)} + + true -> + {found, input} end found @@ -1041,9 +1046,16 @@ defmodule Ash.Actions.ManagedRelationships do case changeset.context[:private][:belongs_to_manage_created][relationship.name][index] do nil -> created = - if is_struct(input) do + if is_struct(input, relationship.destination) do {:ok, input, []} else + input = + if is_struct(input) do + Map.from_struct(input) + else + input + end + relationship.destination |> Ash.Changeset.new() |> Ash.Changeset.for_create(action_name, input, @@ -1078,16 +1090,21 @@ defmodule Ash.Actions.ManagedRelationships do join_keys = params ++ Enum.map(params, &to_string/1) input = - if is_map(input) do - input - else - Enum.into(input, %{}) + cond do + is_struct(input, relationship.destination) -> + input + + is_struct(input) -> + Map.from_struct(input) + + true -> + input end {join_params, regular_params} = split_join_keys(input, join_keys) created = - if is_struct(input) do + if is_struct(input, relationship.destination) do {:ok, input, [], [input]} else relationship.destination @@ -1213,10 +1230,15 @@ defmodule Ash.Actions.ManagedRelationships do {:update, action_name} -> {match, input} = - if is_struct(input) do - {input, %{}} - else - {match, input} + cond do + is_struct(input, relationship.destination) -> + {input, %{}} + + is_struct(input) -> + Map.from_struct(input) + + true -> + {match, input} end match @@ -1242,10 +1264,15 @@ defmodule Ash.Actions.ManagedRelationships do {join_params, regular_params} = split_join_keys(input, join_keys) {match, regular_params} = - if is_struct(regular_params) do - {regular_params, %{}} - else - {match, regular_params} + cond do + is_struct(regular_params, relationship.destination) -> + {regular_params, %{}} + + is_struct(regular_params) -> + Map.from_struct(regular_params) + + true -> + {match, regular_params} end source_value = Map.get(source_record, relationship.source_field) diff --git a/priv/documentation/how_to/upgrading.md b/priv/documentation/how_to/upgrading.md index a63434e9..2226cb92 100644 --- a/priv/documentation/how_to/upgrading.md +++ b/priv/documentation/how_to/upgrading.md @@ -14,4 +14,8 @@ end ### Primary Actions -Primary actions have been simplified for 2.0.0. If there was a single action of a given type before, it would have been marked as `primary?` automatically. Now, `primary?` actions are fully optional, although you may still want to configure them. Certain things like [managing relationships](managing_relationships.md) can be much simpler when paired with primary actions. For a fully explicit experience everywhere, however, you may want to skip primary actions altogether. To make sure your application behaves the same, go to each of your resources and check to see if they only have one action of each type. If they do, mark that single action as `primary?`. Additionally, the `primary_actions?` option has been removed now that all primary actions are explicit. \ No newline at end of file +Primary actions have been simplified for 2.0.0. If there was a single action of a given type before, it would have been marked as `primary?` automatically. Now, `primary?` actions are fully optional, although you may still want to configure them. Certain things like [managing relationships](managing_relationships.md) can be much simpler when paired with primary actions. For a fully explicit experience everywhere, however, you may want to skip primary actions altogether. To make sure your application behaves the same, go to each of your resources and check to see if they only have one action of each type. If they do, mark that single action as `primary?`. Additionally, the `primary_actions?` option has been removed now that all primary actions are explicit. + +### Ash.Error.Query.NotFound + +We used to return/raise this error directly when something wasn't found, but it was the only place in the framework not using an Error Class. So if you had anything matching on `%Ash.Error.Query.NotFound{}` it should instead now match on `%Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{}]}`. \ No newline at end of file