Skip to content

Commit e71637e

Browse files
authored
fix: handle updates on union types containing arrays (#2237)
* test: Add test for union with array type This test demonstrates the bug described in issue #2236, where updates to a property containing a union of an array and another type were not handled correctly. --------- Co-authored-by: Rutger <rutgerdj@users.noreply.github.com>
1 parent c12a174 commit e71637e

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

lib/ash/type/union.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,7 +1299,7 @@ defmodule Ash.Type.Union do
12991299
{:ok, type} <- Keyword.fetch(type_config, :type),
13001300
type_constraints <- Keyword.get(type_config, :constraints, []),
13011301
type <- Ash.Type.get_type(type),
1302-
{:ok, value} <- type.prepare_change(old_value, new_value, type_constraints) do
1302+
{:ok, value} <- Ash.Type.prepare_change(type, old_value, new_value, type_constraints) do
13031303
{:ok, %Ash.Union{type: type_name, value: value}}
13041304
end
13051305
end
@@ -1314,7 +1314,7 @@ defmodule Ash.Type.Union do
13141314
{:ok, type} <- Keyword.fetch(type_config, :type),
13151315
type_constraints <- Keyword.get(type_config, :constraints, []),
13161316
type <- Ash.Type.get_type(type),
1317-
{:ok, value} <- type.prepare_change(nil, new_value, type_constraints) do
1317+
{:ok, value} <- Ash.Type.prepare_change(type, nil, new_value, type_constraints) do
13181318
{:ok, %Ash.Union{type: type_name, value: value}}
13191319
end
13201320
end
@@ -1364,7 +1364,7 @@ defmodule Ash.Type.Union do
13641364
type_constraints <-
13651365
Keyword.put(type_constraints, :__union_tag__, type_config[:tag]),
13661366
type <- Ash.Type.get_type(type),
1367-
{:ok, value} <- type.prepare_change(old_value, new_value, type_constraints) do
1367+
{:ok, value} <- Ash.Type.prepare_change(type, old_value, new_value, type_constraints) do
13681368
{:ok, %Ash.Union{type: type_name, value: value}}
13691369
end
13701370
end

test/type/union_test.exs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,32 @@ defmodule Ash.Test.Filter.UnionTest do
139139
end
140140
end
141141

142+
defmodule ListExample do
143+
use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets
144+
145+
ets do
146+
private? true
147+
end
148+
149+
actions do
150+
defaults create: :*, update: :*
151+
end
152+
153+
attributes do
154+
uuid_primary_key :id
155+
156+
attribute :thing, :union,
157+
public?: true,
158+
constraints: [
159+
types: [
160+
string: [type: :string],
161+
string_array: [type: {:array, :string}],
162+
integer_array: [type: {:array, :integer}]
163+
]
164+
]
165+
end
166+
end
167+
142168
test "it handles UUIDs and strings" do
143169
constraints = [types: [id: [type: :uuid], slug: [type: :string]]]
144170

@@ -460,4 +486,41 @@ defmodule Ash.Test.Filter.UnionTest do
460486
})
461487
|> Ash.update()
462488
end
489+
490+
test "it handles updates to and from array in union types" do
491+
single_value = "Hello"
492+
array_values = ["Hello", "World", "!"]
493+
array_values_2 = [123, 456]
494+
495+
element =
496+
ListExample
497+
|> Ash.Changeset.for_create(:create, %{
498+
thing: %Ash.Union{type: :string, value: single_value}
499+
})
500+
|> Ash.create!()
501+
502+
# Update from single value to array
503+
assert {:ok, %{thing: %{value: ^array_values}} = element} =
504+
element
505+
|> Ash.Changeset.for_update(:update, %{
506+
thing: %Ash.Union{type: :string_array, value: array_values}
507+
})
508+
|> Ash.update()
509+
510+
# Update from array to array of another type
511+
assert {:ok, %{thing: %{value: ^array_values_2}} = element} =
512+
element
513+
|> Ash.Changeset.for_update(:update, %{
514+
thing: %Ash.Union{type: :integer_array, value: array_values_2}
515+
})
516+
|> Ash.update()
517+
518+
# Update from array to single value
519+
assert {:ok, %{thing: %{value: ^single_value}}} =
520+
element
521+
|> Ash.Changeset.for_update(:update, %{
522+
thing: %Ash.Union{type: :string, value: single_value}
523+
})
524+
|> Ash.update()
525+
end
463526
end

0 commit comments

Comments
 (0)