improvement: add read_action option to cascade_destroy

This commit is contained in:
Zach Daniel 2024-08-15 10:49:36 -04:00
parent ce5c080492
commit 2e13d2b0df

View file

@ -7,9 +7,15 @@ defmodule Ash.Resource.Change.CascadeDestroy do
], ],
action: [ action: [
type: :atom, type: :atom,
doc: "The name of the destroy action to call on the related resource", doc:
required: false, "The name of the destroy action to call on the related resource. Uses the primary destroy by default.",
default: :destroy required: false
],
read_action: [
type: :atom,
doc:
"The name of the read action to call on the related resource to find results to be destroyed",
required: false
], ],
return_notifications?: [ return_notifications?: [
type: :boolean, type: :boolean,
@ -127,6 +133,7 @@ defmodule Ash.Resource.Change.CascadeDestroy do
)} )}
relationship -> relationship ->
if opts.action do
case Ash.Resource.Info.action(relationship.destination, opts.action) do case Ash.Resource.Info.action(relationship.destination, opts.action) do
action when action.type == :destroy -> action when action.type == :destroy ->
{:ok, {:ok,
@ -134,7 +141,8 @@ defmodule Ash.Resource.Change.CascadeDestroy do
opts opts
| action: action, | action: action,
relationship: relationship, relationship: relationship,
domain: relationship.domain || Ash.Resource.Info.domain(relationship.destination) domain:
relationship.domain || Ash.Resource.Info.domain(relationship.destination)
}} }}
_ -> _ ->
@ -145,6 +153,15 @@ defmodule Ash.Resource.Change.CascadeDestroy do
destroy: :destroy destroy: :destroy
)} )}
end end
else
{:ok,
%{
opts
| action: Ash.Resource.Info.primary_action!(relationship.destination, :destroy),
relationship: relationship,
domain: relationship.domain || Ash.Resource.Info.domain(relationship.destination)
}}
end
end end
end end
@ -163,7 +180,7 @@ defmodule Ash.Resource.Change.CascadeDestroy do
return_notifications?: opts.return_notifications? return_notifications?: opts.return_notifications?
) )
case related_query(data, opts.relationship) do case related_query(data, opts) do
{:ok, query} -> {:ok, query} ->
Ash.bulk_destroy!(query, action.name, %{}, context_opts) Ash.bulk_destroy!(query, action.name, %{}, context_opts)
@ -195,21 +212,28 @@ defmodule Ash.Resource.Change.CascadeDestroy do
end end
end end
defp related_query(_records, relationship) when relationship.type == :many_to_many, do: :error defp related_query(_records, opts) when opts.relationship.type == :many_to_many, do: :error
defp related_query(records, relationship) do defp related_query(records, opts) do
if Ash.Actions.Read.Relationships.has_parent_expr?(relationship) do if Ash.Actions.Read.Relationships.has_parent_expr?(opts.relationship) do
:error :error
else else
related_query =
if opts.read_action do
Ash.Query.for_read(opts.relationship.destination, opts.read_action, %{})
else
Ash.Query.new(opts.relationship.destination)
end
{:ok, {:ok,
Ash.Actions.Read.Relationships.related_query( Ash.Actions.Read.Relationships.related_query(
relationship.name, opts.relationship.name,
records, records,
Ash.Query.new(relationship.destination), related_query,
Ash.Query.new(relationship.source) Ash.Query.new(opts.relationship.source)
) )
|> elem(1) |> elem(1)
|> filter_by_keys(relationship, records)} |> filter_by_keys(opts.relationship, records)}
end end
end end