mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
improvement: expose union errors with path when tag is set
This commit is contained in:
parent
5549bbf290
commit
8c1f334075
3 changed files with 75 additions and 9 deletions
|
@ -455,10 +455,10 @@ defmodule Ash.Type do
|
|||
|> Ash.Error.flatten_preserving_keywords()
|
||||
|> Enum.map(fn
|
||||
message when is_binary(message) ->
|
||||
[message: message, index: index]
|
||||
[message: message, index: index, path: [index]]
|
||||
|
||||
keyword ->
|
||||
Keyword.put(keyword, :index, index)
|
||||
Keyword.merge(keyword, index: index, path: [index])
|
||||
end)
|
||||
|
||||
{:halt, {:error, errors}}
|
||||
|
|
|
@ -234,10 +234,15 @@ defmodule Ash.Type.Union do
|
|||
Map.get(value, config[:tag], Map.get(value, to_string(config[:tag])))
|
||||
|
||||
tags_equal? =
|
||||
if is_atom(tag_value) do
|
||||
their_tag_value == tag_value || their_tag_value == to_string(tag_value)
|
||||
else
|
||||
their_tag_value == tag_value
|
||||
cond do
|
||||
is_atom(tag_value) ->
|
||||
their_tag_value == tag_value || their_tag_value == to_string(tag_value)
|
||||
|
||||
is_binary(tag_value) && is_atom(their_tag_value) ->
|
||||
their_tag_value == tag_value || to_string(their_tag_value) == tag_value
|
||||
|
||||
true ->
|
||||
their_tag_value == tag_value
|
||||
end
|
||||
|
||||
if tags_equal? do
|
||||
|
@ -253,11 +258,11 @@ defmodule Ash.Type.Union do
|
|||
}}}
|
||||
|
||||
{:error, other} ->
|
||||
{:halt, {:error, "is not a valid #{type_name}: #{inspect(other)}"}}
|
||||
{:halt, {:expose_error, other}}
|
||||
end
|
||||
|
||||
{:error, other} ->
|
||||
{:halt, {:error, "is not a valid #{type_name}: #{inspect(other)}"}}
|
||||
{:halt, {:expose_error, other}}
|
||||
|
||||
:error ->
|
||||
{:halt, {:error, "is not a valid #{type_name}"}}
|
||||
|
@ -302,6 +307,9 @@ defmodule Ash.Type.Union do
|
|||
{:error, errors} ->
|
||||
{:error, error_message(errors)}
|
||||
|
||||
{:expose_error, errors} ->
|
||||
{:error, errors}
|
||||
|
||||
{:ok, value} ->
|
||||
{:ok, value}
|
||||
|
||||
|
|
|
@ -2,6 +2,32 @@ defmodule Ash.Test.Type.UnionTest do
|
|||
@moduledoc false
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
defmodule Foo do
|
||||
use Ash.Resource, data_layer: :embedded
|
||||
|
||||
attributes do
|
||||
attribute :foo, :string, constraints: [match: ~r/foo/]
|
||||
|
||||
attribute :type, :string do
|
||||
writable? false
|
||||
default "foo"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Bar do
|
||||
use Ash.Resource, data_layer: :embedded
|
||||
|
||||
attributes do
|
||||
attribute :bar, :string, constraints: [match: ~r/bar/]
|
||||
|
||||
attribute :type, :string do
|
||||
writable? false
|
||||
default "bar"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "it handles simple types" do
|
||||
constraints = [
|
||||
types: [
|
||||
|
@ -50,6 +76,38 @@ defmodule Ash.Test.Type.UnionTest do
|
|||
assert {:ok, %Ash.Union{value: %{type: :bar, bar: 1}, type: :bar}} =
|
||||
Ash.Type.cast_input(:union, %{type: :bar, bar: 1}, constraints)
|
||||
|
||||
assert {:error, _} = Ash.Type.cast_input(:union, %{type: :baz, bar: 1}, constraints)
|
||||
assert {:error, _} =
|
||||
Ash.Type.cast_input(:union, %{type: :baz, bar: 1}, constraints)
|
||||
end
|
||||
|
||||
test "it handles paths" do
|
||||
constraints = [
|
||||
items: [
|
||||
types: [
|
||||
foo: [
|
||||
type: Foo,
|
||||
tag: :type,
|
||||
tag_value: :foo
|
||||
],
|
||||
bar: [
|
||||
type: Bar,
|
||||
tag: :type,
|
||||
tag_value: :bar
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
{:ok, %{type: type, constraints: constraints}} =
|
||||
Ash.Type.set_type_transformation(%{
|
||||
type: {:array, Ash.Type.Union},
|
||||
constraints: constraints
|
||||
})
|
||||
|
||||
assert {:ok, [%Ash.Union{value: %{type: "foo", foo: "foo"}, type: :foo}]} =
|
||||
Ash.Type.cast_input(type, [%{type: :foo, foo: "foo"}], constraints)
|
||||
|
||||
# assert {:ok, [%Ash.Union{value: %{type: "foo", foo: "foo"}, type: :foo}]} =
|
||||
Ash.Type.cast_input(type, [%{type: :foo, foo: "bar"}], constraints) |> IO.inspect()
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue