mirror of
https://github.com/ash-project/ash_phoenix.git
synced 2024-09-19 06:42:47 +12:00
improvement: honor _union_type
when applying input
This commit is contained in:
parent
2a74d91618
commit
3ae44d7cad
4 changed files with 145 additions and 121 deletions
|
@ -152,7 +152,7 @@ defmodule AshPhoenix.Form.Auto do
|
|||
|
||||
updater =
|
||||
fn opts, data, params ->
|
||||
{type, constraints, tag, tag_value} =
|
||||
{type_name, type, constraints, tag, tag_value} =
|
||||
determine_type(constraints, data, params)
|
||||
|
||||
{embed, constraints, fake_embedded?} =
|
||||
|
@ -177,14 +177,7 @@ defmodule AshPhoenix.Form.Auto do
|
|||
|
||||
transform_params =
|
||||
if fake_embedded? do
|
||||
fn form, params, type ->
|
||||
if type == :nested do
|
||||
AshPhoenix.Form.value(form, :value)
|
||||
else
|
||||
params
|
||||
end
|
||||
|> set_tag_value(tag, tag_value)
|
||||
end
|
||||
union_param_transformer(type_name)
|
||||
else
|
||||
fn _form, params, _type ->
|
||||
set_tag_value(params, tag, tag_value)
|
||||
|
@ -261,14 +254,14 @@ defmodule AshPhoenix.Form.Auto do
|
|||
#{inspect(constraints[:types], pretty: true)}
|
||||
"""
|
||||
|
||||
{_key, config} ->
|
||||
{config[:type], config[:constraints], config[:tag], config[:tag_value]}
|
||||
{key, config} ->
|
||||
{key, config[:type], config[:constraints], config[:tag], config[:tag_value]}
|
||||
end
|
||||
end
|
||||
|
||||
defp determine_type(constraints, %Ash.Union{type: type}, _params) do
|
||||
config = constraints[:types][type]
|
||||
{config[:type], config[:constraints], config[:tag], config[:tag_value]}
|
||||
{type, config[:type], config[:constraints], config[:tag], config[:tag_value]}
|
||||
end
|
||||
|
||||
defp determine_type(constraints, %AshPhoenix.Form.WrappedValue{value: nil}, params)
|
||||
|
@ -277,8 +270,8 @@ defmodule AshPhoenix.Form.Auto do
|
|||
end
|
||||
|
||||
defp determine_type(constraints, nil, params) when params == %{} do
|
||||
{_key, config} = Enum.at(constraints[:types], 0)
|
||||
{config[:type], config[:constraints], config[:tag], config[:tag_value]}
|
||||
{key, config} = Enum.at(constraints[:types], 0)
|
||||
{key, config[:type], config[:constraints], config[:tag], config[:tag_value]}
|
||||
end
|
||||
|
||||
defp determine_type(constraints, data, params) do
|
||||
|
@ -303,8 +296,19 @@ defmodule AshPhoenix.Form.Auto do
|
|||
#{inspect(constraints[:types], pretty: true)}
|
||||
"""
|
||||
|
||||
{_key, config} ->
|
||||
{config[:type], config[:constraints], config[:tag], config[:tag_value]}
|
||||
{key, config} ->
|
||||
{key, config[:type], config[:constraints], config[:tag], config[:tag_value]}
|
||||
end
|
||||
end
|
||||
|
||||
@doc false
|
||||
def union_param_transformer(type_name) do
|
||||
fn form, params, validation_type ->
|
||||
if validation_type == :nested do
|
||||
%Ash.Union{type: type_name, value: AshPhoenix.Form.value(form, :value)}
|
||||
else
|
||||
params
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -371,6 +371,9 @@ defmodule AshPhoenix.Form do
|
|||
def for_action(resource_or_data, action, opts \\ [])
|
||||
|
||||
def for_action(%Ash.Union{value: value, type: type}, action, opts) do
|
||||
opts =
|
||||
Keyword.put_new(opts, :transform_params, AshPhoenix.Form.Auto.union_param_transformer(type))
|
||||
|
||||
form = for_action(value, action, opts)
|
||||
|
||||
%{form | params: Map.put(form.params, "_union_type", to_string(type))}
|
||||
|
|
|
@ -99,111 +99,134 @@ defmodule AshPhoenix.AutoFormTest do
|
|||
end
|
||||
|
||||
test "simple unions" do
|
||||
SimplePost
|
||||
assert %Ash.Union{type: :predefined, value: :update} =
|
||||
SimplePost
|
||||
|> AshPhoenix.Form.for_create(:create,
|
||||
domain: Domain,
|
||||
forms: [
|
||||
auto?: true
|
||||
],
|
||||
params: %{
|
||||
"text" => "foobar"
|
||||
}
|
||||
)
|
||||
|> AshPhoenix.Form.add_form(:union,
|
||||
params: %{"_union_type" => "predefined", "value" => "update"}
|
||||
)
|
||||
|> AshPhoenix.Form.submit!()
|
||||
|> Map.get(:union)
|
||||
end
|
||||
|
||||
test "simple unions with invalid values" do
|
||||
assert_raise Ash.Error.Invalid, ~r/atom must be one of "update", got: :create/, fn ->
|
||||
SimplePost
|
||||
|> AshPhoenix.Form.for_create(:create,
|
||||
domain: Domain,
|
||||
forms: [
|
||||
auto?: true
|
||||
],
|
||||
params: %{
|
||||
"text" => "foobar"
|
||||
}
|
||||
)
|
||||
|> AshPhoenix.Form.add_form(:union,
|
||||
params: %{"_union_type" => "predefined", "value" => "create"}
|
||||
)
|
||||
|> AshPhoenix.Form.submit!()
|
||||
end
|
||||
end
|
||||
|
||||
test "deeply nested unions" do
|
||||
AshPhoenix.Test.DeepNestedUnionResource
|
||||
|> AshPhoenix.Form.for_create(:create,
|
||||
domain: Domain,
|
||||
forms: [
|
||||
auto?: true
|
||||
],
|
||||
]
|
||||
)
|
||||
|> AshPhoenix.Form.add_form(:items,
|
||||
params: %{"subject" => %{"_union_type" => "predefined"}}
|
||||
)
|
||||
|> AshPhoenix.Form.submit!(
|
||||
params: %{
|
||||
"text" => "foobar"
|
||||
"items" => %{
|
||||
"0" => %{
|
||||
"_form_type" => "create",
|
||||
"_touched" => "_form_type,_persistent_id,_touched,subject",
|
||||
"subject" => %{
|
||||
"_form_type" => "create",
|
||||
"_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
||||
"_union_type" => "predefined",
|
||||
"value" => "update"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|> AshPhoenix.Form.add_form(:union, params: %{"type" => "custom"})
|
||||
|> AshPhoenix.Form.submit!()
|
||||
end
|
||||
|> then(fn result ->
|
||||
assert %Ash.Union{value: :update, type: :predefined} === Enum.at(result.items, 0).subject
|
||||
end)
|
||||
|
||||
test "deeply nested unions" do
|
||||
# AshPhoenix.Test.DeepNestedUnionResource
|
||||
# |> AshPhoenix.Form.for_create(:create,
|
||||
# domain: Domain,
|
||||
# forms: [
|
||||
# auto?: true
|
||||
# ]
|
||||
# )
|
||||
# |> AshPhoenix.Form.add_form(:items,
|
||||
# params: %{"subject" => %{"_union_type" => "predefined"}}
|
||||
# )
|
||||
# |> AshPhoenix.Form.submit!(
|
||||
# params: %{
|
||||
# "items" => %{
|
||||
# "0" => %{
|
||||
# "_form_type" => "create",
|
||||
# "_touched" => "_form_type,_persistent_id,_touched,subject",
|
||||
# "subject" => %{
|
||||
# "_form_type" => "create",
|
||||
# "_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
||||
# "_union_type" => "predefined",
|
||||
# "value" => "update"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# )
|
||||
# |> then(fn result ->
|
||||
# assert %Ash.Union{value: :update, type: :predefined} === Enum.at(result.items, 0).subject
|
||||
# end)
|
||||
assert {:error, submitted_with_invalid} =
|
||||
AshPhoenix.Test.DeepNestedUnionResource
|
||||
|> AshPhoenix.Form.for_create(:create,
|
||||
domain: Domain,
|
||||
forms: [
|
||||
auto?: true
|
||||
]
|
||||
)
|
||||
|> AshPhoenix.Form.add_form(:items,
|
||||
params: %{"subject" => %{"_union_type" => "predefined"}}
|
||||
)
|
||||
|> AshPhoenix.Form.submit(
|
||||
params: %{
|
||||
"items" => %{
|
||||
"0" => %{
|
||||
"_form_type" => "create",
|
||||
"_touched" => "_form_type,_persistent_id,_touched,subject",
|
||||
"subject" => %{
|
||||
"_form_type" => "create",
|
||||
"_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
||||
"_union_type" => "predefined",
|
||||
"value" => "this_is_completely_unique"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
# assert {:error, submitted_with_invalid} =
|
||||
# AshPhoenix.Test.DeepNestedUnionResource
|
||||
# |> AshPhoenix.Form.for_create(:create,
|
||||
# domain: Domain,
|
||||
# forms: [
|
||||
# auto?: true
|
||||
# ]
|
||||
# )
|
||||
# |> AshPhoenix.Form.add_form(:items,
|
||||
# params: %{"subject" => %{"_union_type" => "predefined"}}
|
||||
# )
|
||||
# |> AshPhoenix.Form.submit(
|
||||
# params: %{
|
||||
# "items" => %{
|
||||
# "0" => %{
|
||||
# "_form_type" => "create",
|
||||
# "_touched" => "_form_type,_persistent_id,_touched,subject",
|
||||
# "subject" => %{
|
||||
# "_form_type" => "create",
|
||||
# "_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
||||
# "_union_type" => "predefined",
|
||||
# "value" => "this_is_completely_unique"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# )
|
||||
assert %{[:items, 0, :subject] => [value: "is invalid"]} =
|
||||
AshPhoenix.Form.errors(submitted_with_invalid, for_path: :all)
|
||||
|
||||
# assert %{[:items, 0, :subject] => [value: "is invalid"]} =
|
||||
# AshPhoenix.Form.errors(submitted_with_invalid, for_path: :all)
|
||||
|
||||
# AshPhoenix.Test.DeepNestedUnionResource
|
||||
# |> AshPhoenix.Form.for_create(:create,
|
||||
# domain: Domain,
|
||||
# forms: [
|
||||
# auto?: true
|
||||
# ]
|
||||
# )
|
||||
# |> AshPhoenix.Form.add_form(:items,
|
||||
# params: %{"subject" => %{"_union_type" => "predefined"}}
|
||||
# )
|
||||
# |> AshPhoenix.Form.submit!(
|
||||
# params: %{
|
||||
# "items" => %{
|
||||
# "0" => %{
|
||||
# "_form_type" => "create",
|
||||
# "_touched" => "_form_type,_persistent_id,_touched,subject",
|
||||
# "subject" => %{
|
||||
# "_form_type" => "create",
|
||||
# "_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
||||
# "_union_type" => "custom",
|
||||
# "value" => "different"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# )
|
||||
# |> then(fn result ->
|
||||
# assert %Ash.Union{value: "different", type: :custom} === Enum.at(result.items, 0).subject
|
||||
# end)
|
||||
AshPhoenix.Test.DeepNestedUnionResource
|
||||
|> AshPhoenix.Form.for_create(:create,
|
||||
domain: Domain,
|
||||
forms: [
|
||||
auto?: true
|
||||
]
|
||||
)
|
||||
|> AshPhoenix.Form.add_form(:items,
|
||||
params: %{"subject" => %{"_union_type" => "predefined"}}
|
||||
)
|
||||
|> AshPhoenix.Form.submit!(
|
||||
params: %{
|
||||
"items" => %{
|
||||
"0" => %{
|
||||
"_form_type" => "create",
|
||||
"_touched" => "_form_type,_persistent_id,_touched,subject",
|
||||
"subject" => %{
|
||||
"_form_type" => "create",
|
||||
"_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
||||
"_union_type" => "custom",
|
||||
"value" => "different"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|> then(fn result ->
|
||||
assert %Ash.Union{value: "different", type: :custom} === Enum.at(result.items, 0).subject
|
||||
end)
|
||||
|
||||
AshPhoenix.Test.DeepNestedUnionResource
|
||||
|> AshPhoenix.Form.for_create(:create,
|
||||
|
|
|
@ -3,18 +3,12 @@ defmodule AshPhoenix.Test.SimplePost.SimpleUnion do
|
|||
subtype_of: :union,
|
||||
constraints: [
|
||||
types: [
|
||||
custom: [
|
||||
type: :string
|
||||
],
|
||||
predefined: [
|
||||
type: :atom,
|
||||
constraints: [one_of: [:update]],
|
||||
tag: :type,
|
||||
tag_value: :predefined,
|
||||
cast_tag?: true
|
||||
],
|
||||
custom: [
|
||||
type: :string,
|
||||
tag: :type,
|
||||
tag_value: :custom,
|
||||
cast_tag?: true
|
||||
constraints: [one_of: [:update]]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue