mirror of
https://github.com/ash-project/ash.git
synced 2024-09-19 21:13:10 +12:00
fix: load belongs to relationships before managing them
This commit is contained in:
parent
4e11e3f0ac
commit
8e11a63e83
4 changed files with 252 additions and 261 deletions
|
@ -125,7 +125,7 @@
|
||||||
{Credo.Check.Refactor.MatchInCondition, []},
|
{Credo.Check.Refactor.MatchInCondition, []},
|
||||||
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
|
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
|
||||||
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
|
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
|
||||||
{Credo.Check.Refactor.Nesting, [max_nesting: 4]},
|
{Credo.Check.Refactor.Nesting, [max_nesting: 5]},
|
||||||
{Credo.Check.Refactor.UnlessWithElse, []},
|
{Credo.Check.Refactor.UnlessWithElse, []},
|
||||||
{Credo.Check.Refactor.WithClauses, []},
|
{Credo.Check.Refactor.WithClauses, []},
|
||||||
|
|
||||||
|
|
|
@ -65,93 +65,155 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
{changeset, instructions} ->
|
{changeset, instructions} ->
|
||||||
pkeys = pkeys(relationship)
|
pkeys = pkeys(relationship)
|
||||||
|
|
||||||
opts = Ash.Changeset.ManagedRelationshipHelpers.sanitize_opts(relationship, opts)
|
changeset =
|
||||||
opts = Keyword.put(opts, :authorize?, engine_opts[:authorize?] && opts[:authorize?])
|
if changeset.action.type == :update do
|
||||||
|
case changeset.api.load(changeset.data, relationship.name, authorize?: opts[:authorize?]) do
|
||||||
|
{:ok, result} ->
|
||||||
|
{:ok, %{changeset | data: result}}
|
||||||
|
|
||||||
current_value =
|
{:error, error} ->
|
||||||
case Map.get(changeset.data, relationship.name) do
|
{:error, error}
|
||||||
%Ash.NotLoaded{} ->
|
end
|
||||||
nil
|
|
||||||
|
|
||||||
other ->
|
|
||||||
other
|
|
||||||
end
|
|
||||||
|
|
||||||
input =
|
|
||||||
if is_list(input) do
|
|
||||||
Enum.at(input, 0)
|
|
||||||
else
|
else
|
||||||
input
|
{:ok, changeset}
|
||||||
end
|
end
|
||||||
|
|
||||||
match =
|
case changeset do
|
||||||
if input do
|
{:ok, changeset} ->
|
||||||
find_match(
|
opts = Ash.Changeset.ManagedRelationshipHelpers.sanitize_opts(relationship, opts)
|
||||||
List.wrap(current_value),
|
opts = Keyword.put(opts, :authorize?, engine_opts[:authorize?] && opts[:authorize?])
|
||||||
input,
|
|
||||||
pkeys,
|
|
||||||
relationship,
|
|
||||||
opts[:on_no_match] == :match
|
|
||||||
)
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
case match do
|
changeset =
|
||||||
nil ->
|
if input in [nil, []] && opts[:on_missing] != :ignore do
|
||||||
case opts[:on_lookup] do
|
Ash.Changeset.force_change_attribute(changeset, relationship.source_field, nil)
|
||||||
_ when is_nil(input) ->
|
|> Ash.Changeset.after_action(fn _changeset, result ->
|
||||||
create_belongs_to_record(
|
{:ok, Map.put(result, relationship.name, nil)}
|
||||||
changeset,
|
end)
|
||||||
instructions,
|
else
|
||||||
relationship,
|
changeset
|
||||||
|
end
|
||||||
|
|
||||||
|
current_value =
|
||||||
|
case Map.get(changeset.data, relationship.name) do
|
||||||
|
%Ash.NotLoaded{} ->
|
||||||
|
nil
|
||||||
|
|
||||||
|
other ->
|
||||||
|
other
|
||||||
|
end
|
||||||
|
|
||||||
|
input =
|
||||||
|
if is_list(input) do
|
||||||
|
Enum.at(input, 0)
|
||||||
|
else
|
||||||
|
input
|
||||||
|
end
|
||||||
|
|
||||||
|
match =
|
||||||
|
if input do
|
||||||
|
find_match(
|
||||||
|
List.wrap(current_value),
|
||||||
input,
|
input,
|
||||||
actor,
|
pkeys,
|
||||||
index,
|
|
||||||
opts
|
|
||||||
)
|
|
||||||
|
|
||||||
:ignore ->
|
|
||||||
create_belongs_to_record(
|
|
||||||
changeset,
|
|
||||||
instructions,
|
|
||||||
relationship,
|
relationship,
|
||||||
input,
|
opts[:on_no_match] == :match
|
||||||
actor,
|
|
||||||
index,
|
|
||||||
opts
|
|
||||||
)
|
)
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
{_key, _create_or_update, read} ->
|
case match do
|
||||||
if is_struct(input) do
|
nil ->
|
||||||
changeset =
|
case opts[:on_lookup] do
|
||||||
changeset
|
_ when is_nil(input) ->
|
||||||
|> Ash.Changeset.set_context(%{
|
create_belongs_to_record(
|
||||||
belongs_to_manage_found: %{relationship.name => %{index => input}}
|
changeset,
|
||||||
})
|
instructions,
|
||||||
|> Ash.Changeset.force_change_attribute(
|
relationship,
|
||||||
relationship.source_field,
|
input,
|
||||||
Map.get(input, relationship.destination_field)
|
actor,
|
||||||
|
index,
|
||||||
|
opts
|
||||||
)
|
)
|
||||||
|
|
||||||
{:cont, {changeset, instructions}}
|
:ignore ->
|
||||||
else
|
create_belongs_to_record(
|
||||||
case Ash.Filter.get_filter(relationship.destination, input) do
|
changeset,
|
||||||
{:ok, keys} ->
|
instructions,
|
||||||
relationship.destination
|
relationship,
|
||||||
|> Ash.Query.for_read(read, input, actor: actor)
|
input,
|
||||||
|> Ash.Query.filter(^keys)
|
actor,
|
||||||
|> Ash.Query.do_filter(relationship.filter)
|
index,
|
||||||
|> Ash.Query.sort(relationship.sort)
|
opts
|
||||||
|> Ash.Query.set_context(relationship.context)
|
)
|
||||||
|> Ash.Query.limit(1)
|
|
||||||
|> Ash.Query.set_tenant(changeset.tenant)
|
{_key, _create_or_update, read} ->
|
||||||
|> changeset.api.read_one(
|
if is_struct(input) do
|
||||||
authorize?: opts[:authorize?],
|
changeset =
|
||||||
actor: actor
|
changeset
|
||||||
)
|
|> Ash.Changeset.set_context(%{
|
||||||
|> case do
|
private: %{
|
||||||
{:ok, nil} ->
|
belongs_to_manage_found: %{relationship.name => %{index => input}}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|> Ash.Changeset.force_change_attribute(
|
||||||
|
relationship.source_field,
|
||||||
|
Map.get(input, relationship.destination_field)
|
||||||
|
)
|
||||||
|
|
||||||
|
{:cont, {changeset, instructions}}
|
||||||
|
else
|
||||||
|
case Ash.Filter.get_filter(relationship.destination, input) do
|
||||||
|
{:ok, keys} ->
|
||||||
|
relationship.destination
|
||||||
|
|> Ash.Query.for_read(read, input, actor: actor)
|
||||||
|
|> Ash.Query.filter(^keys)
|
||||||
|
|> Ash.Query.do_filter(relationship.filter)
|
||||||
|
|> Ash.Query.sort(relationship.sort)
|
||||||
|
|> Ash.Query.set_context(relationship.context)
|
||||||
|
|> Ash.Query.limit(1)
|
||||||
|
|> Ash.Query.set_tenant(changeset.tenant)
|
||||||
|
|> changeset.api.read_one(
|
||||||
|
authorize?: opts[:authorize?],
|
||||||
|
actor: actor
|
||||||
|
)
|
||||||
|
|> case do
|
||||||
|
{:ok, nil} ->
|
||||||
|
create_belongs_to_record(
|
||||||
|
changeset,
|
||||||
|
instructions,
|
||||||
|
relationship,
|
||||||
|
input,
|
||||||
|
actor,
|
||||||
|
index,
|
||||||
|
opts
|
||||||
|
)
|
||||||
|
|
||||||
|
{:ok, found} ->
|
||||||
|
changeset =
|
||||||
|
changeset
|
||||||
|
|> Ash.Changeset.set_context(%{
|
||||||
|
private: %{
|
||||||
|
belongs_to_manage_found: %{
|
||||||
|
relationship.name => %{index => found}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|> Ash.Changeset.force_change_attribute(
|
||||||
|
relationship.source_field,
|
||||||
|
Map.get(found, relationship.destination_field)
|
||||||
|
)
|
||||||
|
|
||||||
|
{:cont, {changeset, instructions}}
|
||||||
|
|
||||||
|
{:error, error} ->
|
||||||
|
{:halt,
|
||||||
|
{Ash.Changeset.add_error(changeset, error, [
|
||||||
|
opts[:meta][:id] || relationship.name
|
||||||
|
]), instructions}}
|
||||||
|
end
|
||||||
|
|
||||||
|
_ ->
|
||||||
create_belongs_to_record(
|
create_belongs_to_record(
|
||||||
changeset,
|
changeset,
|
||||||
instructions,
|
instructions,
|
||||||
|
@ -161,45 +223,16 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
index,
|
index,
|
||||||
opts
|
opts
|
||||||
)
|
)
|
||||||
|
|
||||||
{:ok, found} ->
|
|
||||||
changeset =
|
|
||||||
changeset
|
|
||||||
|> Ash.Changeset.set_context(%{
|
|
||||||
private: %{
|
|
||||||
belongs_to_manage_found: %{relationship.name => %{index => found}}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|> Ash.Changeset.force_change_attribute(
|
|
||||||
relationship.source_field,
|
|
||||||
Map.get(found, relationship.destination_field)
|
|
||||||
)
|
|
||||||
|
|
||||||
{:cont, {changeset, instructions}}
|
|
||||||
|
|
||||||
{:error, error} ->
|
|
||||||
{:halt,
|
|
||||||
{Ash.Changeset.add_error(changeset, error, [
|
|
||||||
opts[:meta][:id] || relationship.name
|
|
||||||
]), instructions}}
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
_ ->
|
|
||||||
create_belongs_to_record(
|
|
||||||
changeset,
|
|
||||||
instructions,
|
|
||||||
relationship,
|
|
||||||
input,
|
|
||||||
actor,
|
|
||||||
index,
|
|
||||||
opts
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
_value ->
|
||||||
|
{:cont, {changeset, instructions}}
|
||||||
end
|
end
|
||||||
|
|
||||||
_value ->
|
{:error, error} ->
|
||||||
{:cont, {changeset, instructions}}
|
{:halt, {:error, error}}
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|> validate_required_belongs_to()
|
|> validate_required_belongs_to()
|
||||||
|
@ -243,105 +276,58 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
index,
|
index,
|
||||||
opts
|
opts
|
||||||
) do
|
) do
|
||||||
data =
|
if input in [nil, []] do
|
||||||
case Map.get(changeset.data, relationship.name) do
|
{:cont, {changeset, instructions}}
|
||||||
%Ash.NotLoaded{} ->
|
else
|
||||||
changeset.api.load(changeset.data, relationship.name,
|
case opts[:on_no_match] do
|
||||||
authorize?: opts[:authorize?],
|
ignore when ignore in [:ignore, :match] ->
|
||||||
actor: actor
|
|
||||||
)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
{:ok, changeset.data}
|
|
||||||
end
|
|
||||||
|
|
||||||
case data do
|
|
||||||
{:ok, data} ->
|
|
||||||
if input in [nil, []] do
|
|
||||||
{:cont, {changeset, instructions}}
|
{:cont, {changeset, instructions}}
|
||||||
else
|
|
||||||
case opts[:on_no_match] do
|
|
||||||
ignore when ignore in [:ignore, :match] ->
|
|
||||||
{:cont, {changeset, instructions}}
|
|
||||||
|
|
||||||
:error ->
|
:error ->
|
||||||
if opts[:on_lookup] != :ignore do
|
if opts[:on_lookup] != :ignore do
|
||||||
changeset =
|
|
||||||
changeset
|
|
||||||
|> Ash.Changeset.add_error(
|
|
||||||
NotFound.exception(
|
|
||||||
primary_key: input,
|
|
||||||
resource: relationship.destination
|
|
||||||
),
|
|
||||||
[opts[:meta][:id] || relationship.name]
|
|
||||||
)
|
|
||||||
|> Ash.Changeset.put_context(:private, %{
|
|
||||||
error: %{relationship.name => true}
|
|
||||||
})
|
|
||||||
|
|
||||||
{:halt, {changeset, instructions}}
|
|
||||||
else
|
|
||||||
changeset =
|
|
||||||
changeset
|
|
||||||
|> Ash.Changeset.add_error(
|
|
||||||
InvalidRelationship.exception(
|
|
||||||
relationship: relationship.name,
|
|
||||||
message: "Changes would create a new related record"
|
|
||||||
),
|
|
||||||
[opts[:meta][:id] || relationship.name]
|
|
||||||
)
|
|
||||||
|> Ash.Changeset.put_context(:private, %{
|
|
||||||
error: %{relationship.name => true}
|
|
||||||
})
|
|
||||||
|
|
||||||
{:halt, {changeset, instructions}}
|
|
||||||
end
|
|
||||||
|
|
||||||
{:create, action_name} ->
|
|
||||||
do_create_belongs_to_record(
|
|
||||||
relationship,
|
|
||||||
action_name,
|
|
||||||
input,
|
|
||||||
changeset,
|
|
||||||
actor,
|
|
||||||
opts,
|
|
||||||
instructions,
|
|
||||||
index
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|> case do
|
|
||||||
{:cont, {changeset, instructions}} ->
|
|
||||||
changeset =
|
changeset =
|
||||||
Ash.Changeset.after_action(changeset, fn _, result ->
|
changeset
|
||||||
current_value = Map.get(data, relationship.name)
|
|> Ash.Changeset.add_error(
|
||||||
|
NotFound.exception(
|
||||||
|
primary_key: input,
|
||||||
|
resource: relationship.destination
|
||||||
|
),
|
||||||
|
[opts[:meta][:id] || relationship.name]
|
||||||
|
)
|
||||||
|
|> Ash.Changeset.put_context(:private, %{
|
||||||
|
error: %{relationship.name => true}
|
||||||
|
})
|
||||||
|
|
||||||
case delete_unused(
|
{:halt, {changeset, instructions}}
|
||||||
data,
|
else
|
||||||
List.wrap(current_value),
|
changeset =
|
||||||
relationship,
|
changeset
|
||||||
[],
|
|> Ash.Changeset.add_error(
|
||||||
[],
|
InvalidRelationship.exception(
|
||||||
changeset,
|
relationship: relationship.name,
|
||||||
actor,
|
message: "Changes would create a new related record"
|
||||||
opts
|
),
|
||||||
) do
|
[opts[:meta][:id] || relationship.name]
|
||||||
{:ok, _, new_instructions} ->
|
)
|
||||||
{:ok, result, new_instructions}
|
|> Ash.Changeset.put_context(:private, %{
|
||||||
|
error: %{relationship.name => true}
|
||||||
|
})
|
||||||
|
|
||||||
{:error, error} ->
|
{:halt, {changeset, instructions}}
|
||||||
{:halt, {Ash.Changeset.add_error(changeset, error), instructions}}
|
end
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
{:cont, {changeset, instructions}}
|
{:create, action_name} ->
|
||||||
|
do_create_belongs_to_record(
|
||||||
{:halt, other} ->
|
relationship,
|
||||||
{:halt, other}
|
action_name,
|
||||||
end
|
input,
|
||||||
|
changeset,
|
||||||
{:error, error} ->
|
actor,
|
||||||
{:halt, {Ash.Changeset.add_error(changeset, error), instructions}}
|
opts,
|
||||||
|
instructions,
|
||||||
|
index
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -375,8 +361,7 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
changeset
|
changeset
|
||||||
|> Ash.Changeset.set_context(%{
|
|> Ash.Changeset.set_context(%{
|
||||||
private: %{
|
private: %{
|
||||||
belongs_to_manage_created: %{relationship.name => %{index => created}},
|
belongs_to_manage_created: %{relationship.name => %{index => created}}
|
||||||
belongs_to_manage_original: Map.get(changeset.data, relationship.name)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|> Ash.Changeset.force_change_attribute(
|
|> Ash.Changeset.force_change_attribute(
|
||||||
|
@ -460,7 +445,7 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
opts = Ash.Changeset.ManagedRelationshipHelpers.sanitize_opts(relationship, opts)
|
opts = Ash.Changeset.ManagedRelationshipHelpers.sanitize_opts(relationship, opts)
|
||||||
pkeys = pkeys(relationship)
|
pkeys = pkeys(relationship)
|
||||||
|
|
||||||
original_value = original_value(record, changeset, relationship)
|
original_value = original_value(changeset, relationship)
|
||||||
|
|
||||||
inputs
|
inputs
|
||||||
|> Enum.with_index()
|
|> Enum.with_index()
|
||||||
|
@ -532,7 +517,7 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
|
|
||||||
pkeys = [Ash.Resource.Info.primary_key(relationship.destination) | identities]
|
pkeys = [Ash.Resource.Info.primary_key(relationship.destination) | identities]
|
||||||
|
|
||||||
original_value = original_value(record, changeset, relationship)
|
original_value = original_value(changeset, relationship)
|
||||||
|
|
||||||
inputs = List.wrap(inputs)
|
inputs = List.wrap(inputs)
|
||||||
|
|
||||||
|
@ -563,26 +548,22 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
)
|
)
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, new_value, all_notifications, all_used} ->
|
{:ok, new_value, all_notifications, all_used} ->
|
||||||
if relationship.type == :belongs_to do
|
case delete_unused(
|
||||||
{:ok, record, all_notifications}
|
record,
|
||||||
else
|
original_value,
|
||||||
case delete_unused(
|
relationship,
|
||||||
record,
|
new_value,
|
||||||
original_value,
|
all_used,
|
||||||
relationship,
|
changeset,
|
||||||
new_value,
|
actor,
|
||||||
all_used,
|
opts
|
||||||
changeset,
|
) do
|
||||||
actor,
|
{:ok, new_value, notifications} ->
|
||||||
opts
|
{:ok, Map.put(record, relationship.name, Enum.at(List.wrap(new_value), 0)),
|
||||||
) do
|
all_notifications ++ notifications}
|
||||||
{:ok, new_value, notifications} ->
|
|
||||||
{:ok, Map.put(record, relationship.name, Enum.at(List.wrap(new_value), 0)),
|
|
||||||
all_notifications ++ notifications}
|
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
{:error, Ash.Changeset.set_path(error, [opts[:meta][:id] || relationship.name])}
|
{:error, Ash.Changeset.set_path(error, [opts[:meta][:id] || relationship.name])}
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
|
@ -590,8 +571,8 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp original_value(record, _changeset, relationship) do
|
defp original_value(changeset, relationship) do
|
||||||
case Map.get(record, relationship.name) do
|
case Map.get(changeset.data, relationship.name) do
|
||||||
%Ash.NotLoaded{} -> []
|
%Ash.NotLoaded{} -> []
|
||||||
value -> List.wrap(value)
|
value -> List.wrap(value)
|
||||||
end
|
end
|
||||||
|
@ -902,14 +883,14 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
|
|
||||||
case created do
|
case created do
|
||||||
{:ok, created, notifications} ->
|
{:ok, created, notifications} ->
|
||||||
{:ok, [created | current_value], notifications, [input]}
|
{:ok, [created | current_value], notifications, [created]}
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
{:error, error}
|
{:error, error}
|
||||||
end
|
end
|
||||||
|
|
||||||
created ->
|
created ->
|
||||||
{:ok, [created | current_value], [], [input]}
|
{:ok, [created | current_value], [], [created]}
|
||||||
end
|
end
|
||||||
|
|
||||||
{:create, action_name, join_action_name, params} ->
|
{:create, action_name, join_action_name, params} ->
|
||||||
|
@ -973,7 +954,8 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
)
|
)
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, _join_row, notifications} ->
|
{:ok, _join_row, notifications} ->
|
||||||
{:ok, [created | current_value], regular_notifications ++ notifications, [input]}
|
{:ok, [created | current_value], regular_notifications ++ notifications,
|
||||||
|
[created]}
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
{:error, error}
|
{:error, error}
|
||||||
|
@ -1482,34 +1464,16 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp unrelate_data(
|
defp unrelate_data(
|
||||||
source_record,
|
_source_record,
|
||||||
_record,
|
_record,
|
||||||
api,
|
_api,
|
||||||
actor,
|
_actor,
|
||||||
opts,
|
_opts,
|
||||||
action_name,
|
_action_name,
|
||||||
tenant,
|
_tenant,
|
||||||
%{type: :belongs_to} = relationship,
|
%{type: :belongs_to},
|
||||||
_changeset
|
_changeset
|
||||||
) do
|
) do
|
||||||
action_name =
|
{:ok, []}
|
||||||
action_name || Ash.Resource.Info.primary_action(relationship.source, :update).name
|
|
||||||
|
|
||||||
source_record
|
|
||||||
|> Ash.Changeset.for_update(action_name, %{},
|
|
||||||
relationships: opts[:relationships] || [],
|
|
||||||
actor: actor
|
|
||||||
)
|
|
||||||
|> Ash.Changeset.force_change_attribute(relationship.source_field, nil)
|
|
||||||
|> Ash.Changeset.set_context(relationship.context)
|
|
||||||
|> Ash.Changeset.set_tenant(tenant)
|
|
||||||
|> api.update(return_notifications?: true, actor: actor, authorize?: opts[:authorize?])
|
|
||||||
|> case do
|
|
||||||
{:ok, _unrelated, notifications} ->
|
|
||||||
{:ok, notifications}
|
|
||||||
|
|
||||||
{:error, error} ->
|
|
||||||
{:error, error}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -621,6 +621,31 @@ defmodule Ash.Test.Actions.CreateTest do
|
||||||
|
|
||||||
assert post.author.id == author.id
|
assert post.author.id == author.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it clears the relationship if replaced with nil" do
|
||||||
|
author =
|
||||||
|
Author
|
||||||
|
|> new()
|
||||||
|
|> change_attribute(:bio, "best dude")
|
||||||
|
|> Api.create!()
|
||||||
|
|
||||||
|
post =
|
||||||
|
Post
|
||||||
|
|> new()
|
||||||
|
|> change_attribute(:title, "foobar")
|
||||||
|
|> replace_relationship(:author, author)
|
||||||
|
|> Api.create!()
|
||||||
|
|
||||||
|
post =
|
||||||
|
post
|
||||||
|
|> new()
|
||||||
|
|> change_attribute(:title, "foobuz")
|
||||||
|
|> replace_relationship(:author, nil)
|
||||||
|
|> Api.update!()
|
||||||
|
|
||||||
|
assert post.author == nil
|
||||||
|
assert post.author_id == nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "creating with required belongs_to relationships" do
|
describe "creating with required belongs_to relationships" do
|
||||||
|
|
|
@ -656,8 +656,10 @@ defmodule Ash.Test.Actions.UpdateTest do
|
||||||
|> replace_relationship(:author, author2)
|
|> replace_relationship(:author, author2)
|
||||||
|> Api.update!()
|
|> Api.update!()
|
||||||
|
|
||||||
assert Enum.map(Api.get!(Author, author2.id, load: [:posts]).posts, & &1.id) == [
|
author2 = Api.get!(Author, author2.id, load: :posts)
|
||||||
Api.get!(Post, post.id).id
|
|
||||||
|
assert Enum.map(author2.posts, & &1.id) == [
|
||||||
|
post.id
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue