Skip to content

Commit 7109cc4

Browse files
authored
fix: cascade change action selection (#2193)
1 parent 1d96a2c commit 7109cc4

File tree

4 files changed

+120
-8
lines changed

4 files changed

+120
-8
lines changed

lib/ash/resource/change/cascade_destroy.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,14 +354,14 @@ defmodule Ash.Resource.Change.CascadeDestroy do
354354
defp related_query(_records, opts, _) when opts.relationship.type == :many_to_many, do: :error
355355

356356
defp related_query(records, opts, context_opts) do
357-
read_action_name = opts.read_action || opts.relationship.read_action
357+
read_action_name =
358+
opts.read_action || opts.relationship.read_action || opts.action.atomic_upgrade_with
358359

359360
read_action =
360361
if read_action_name do
361362
Ash.Resource.Info.action(opts.relationship.destination, read_action_name)
362363
else
363-
opts.action.atomic_upgrade_with ||
364-
Ash.Resource.Info.primary_action!(opts.relationship.destination, :read)
364+
Ash.Resource.Info.primary_action!(opts.relationship.destination, :read)
365365
end
366366

367367
related_query =

lib/ash/resource/change/cascade_update.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,14 @@ defmodule Ash.Resource.Change.CascadeUpdate do
268268
do: :error
269269

270270
defp related_query(data, opts, context_opts) do
271-
read_action_name = opts.read_action || opts.relationship.read_action
271+
read_action_name =
272+
opts.read_action || opts.relationship.read_action || opts.action.atomic_upgrade_with
272273

273274
read_action =
274275
if read_action_name do
275276
Ash.Resource.Info.action(opts.relationship.destination, read_action_name)
276277
else
277-
opts.action.atomic_upgrade_with ||
278-
Ash.Resource.Info.primary_action!(opts.relationship.destination, :read)
278+
Ash.Resource.Info.primary_action!(opts.relationship.destination, :read)
279279
end
280280

281281
related_query =

test/resource/changes/cascade_destroy_test.exs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ defmodule Ash.Test.Resource.Change.CascadeDestroy do
3737
change cascade_destroy(:posts, return_notifications?: true)
3838
end
3939

40+
destroy :destroy_with_atomic_upgrade do
41+
change cascade_destroy(:posts,
42+
action: :destroy_with_atomic_upgrade,
43+
return_notifications?: true
44+
)
45+
end
46+
4047
destroy :no_notification_destroy do
4148
change cascade_destroy(:posts,
4249
return_notifications?: true,
@@ -52,6 +59,7 @@ defmodule Ash.Test.Resource.Change.CascadeDestroy do
5259
code_interface do
5360
define :create
5461
define :destroy
62+
define :destroy_with_atomic_upgrade
5563
define :no_notification_destroy
5664
define :read
5765
end
@@ -68,6 +76,19 @@ defmodule Ash.Test.Resource.Change.CascadeDestroy do
6876
actions do
6977
defaults [:read, create: :*]
7078

79+
read :custom_read do
80+
pagination keyset?: true, required?: false
81+
82+
prepare fn query, _ ->
83+
Agent.update(
84+
Test.Agent,
85+
&%{&1 | custom_read_used: true}
86+
)
87+
88+
query
89+
end
90+
end
91+
7192
destroy :destroy do
7293
primary? true
7394
require_atomic? false
@@ -82,6 +103,20 @@ defmodule Ash.Test.Resource.Change.CascadeDestroy do
82103
end)
83104
end
84105

106+
destroy :destroy_with_atomic_upgrade do
107+
atomic_upgrade_with :custom_read
108+
require_atomic? false
109+
110+
change before_action(fn changeset, _ ->
111+
Agent.update(
112+
Test.Agent,
113+
&%{&1 | destroys: MapSet.put(&1.destroys, changeset.data.id)}
114+
)
115+
116+
changeset
117+
end)
118+
end
119+
85120
destroy :no_notification_destroy do
86121
end
87122
end
@@ -98,7 +133,10 @@ defmodule Ash.Test.Resource.Change.CascadeDestroy do
98133

99134
setup do
100135
{:ok, pid} =
101-
start_supervised({Agent, fn -> %{destroys: MapSet.new(), notifications: MapSet.new()} end})
136+
start_supervised(
137+
{Agent,
138+
fn -> %{destroys: MapSet.new(), notifications: MapSet.new(), custom_read_used: false} end}
139+
)
102140

103141
Process.register(pid, Test.Agent)
104142

@@ -173,4 +211,23 @@ defmodule Ash.Test.Resource.Change.CascadeDestroy do
173211
Author.destroy!(author.id)
174212
assert [] = Author.read!()
175213
end
214+
215+
test "uses atomic_upgrade_with action when specified" do
216+
author = Author.create!(%{})
217+
218+
post_ids =
219+
1..3
220+
|> Enum.map(fn _ -> Post.create!(%{author_id: author.id}) end)
221+
|> MapSet.new(& &1.id)
222+
223+
Author.destroy_with_atomic_upgrade!(author)
224+
225+
assert Agent.get(Test.Agent, & &1.custom_read_used) == true
226+
227+
deleted_ids = Agent.get(Test.Agent, & &1.destroys)
228+
assert MapSet.equal?(post_ids, deleted_ids)
229+
230+
assert [] = Post.read!()
231+
assert [] = Author.read!()
232+
end
176233
end

test/resource/changes/cascade_update_test.exs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ defmodule Ash.Test.Resource.Change.CascadeUpdate do
4545
)
4646
end
4747

48+
update :update_with_atomic_upgrade do
49+
require_atomic? false
50+
skip_unknown_inputs [:content]
51+
52+
change cascade_update(:posts,
53+
action: :update_with_atomic_upgrade,
54+
copy_inputs: [:name, :content],
55+
return_notifications?: true
56+
)
57+
end
58+
4859
update :update_atomic do
4960
change cascade_update(:posts,
5061
copy_inputs: [:name]
@@ -72,6 +83,7 @@ defmodule Ash.Test.Resource.Change.CascadeUpdate do
7283
code_interface do
7384
define :create
7485
define :update
86+
define :update_with_atomic_upgrade
7587
define :no_notification_update
7688
define :read
7789
end
@@ -90,6 +102,19 @@ defmodule Ash.Test.Resource.Change.CascadeUpdate do
90102
default_accept :*
91103
defaults [:read, create: :*]
92104

105+
read :custom_read do
106+
pagination keyset?: true, required?: false
107+
108+
prepare fn query, _ ->
109+
Agent.update(
110+
Test.Agent,
111+
&%{&1 | custom_read_used: true}
112+
)
113+
114+
query
115+
end
116+
end
117+
93118
update :update do
94119
primary? true
95120
require_atomic? false
@@ -113,6 +138,12 @@ defmodule Ash.Test.Resource.Change.CascadeUpdate do
113138
end)
114139
end
115140

141+
update :update_with_atomic_upgrade do
142+
atomic_upgrade_with :custom_read
143+
require_atomic? false
144+
skip_unknown_inputs [:content]
145+
end
146+
116147
update :no_notification_update do
117148
end
118149
end
@@ -191,7 +222,10 @@ defmodule Ash.Test.Resource.Change.CascadeUpdate do
191222

192223
setup do
193224
{:ok, pid} =
194-
start_supervised({Agent, fn -> %{updates: MapSet.new(), notifications: MapSet.new()} end})
225+
start_supervised(
226+
{Agent,
227+
fn -> %{updates: MapSet.new(), notifications: MapSet.new(), custom_read_used: false} end}
228+
)
195229

196230
Process.register(pid, Test.Agent)
197231

@@ -289,4 +323,25 @@ defmodule Ash.Test.Resource.Change.CascadeUpdate do
289323
a2 = Ash.get!(Author, author.id)
290324
assert ^name = a2.name
291325
end
326+
327+
test "uses atomic_upgrade_with action when specified" do
328+
author = Author.create!(%{})
329+
post1 = Post.create!(%{author_id: author.id})
330+
post2 = Post.create!(%{author_id: author.id})
331+
332+
name = "Ash Framework"
333+
content = "Is great!"
334+
335+
author |> Author.update_with_atomic_upgrade!(%{name: name, content: content})
336+
337+
assert Agent.get(Test.Agent, & &1.custom_read_used) == true
338+
339+
a = Ash.get!(Author, author.id)
340+
p = Ash.get!(Post, post1.id)
341+
p2 = Ash.get!(Post, post2.id)
342+
343+
assert ^name = a.name
344+
assert ^name = p.name
345+
assert ^name = p2.name
346+
end
292347
end

0 commit comments

Comments
 (0)