improvement: properly get invalid values provided to forms

This commit is contained in:
Zach Daniel 2023-11-27 19:48:02 -05:00
parent 560fa6689d
commit 6ddddf7316
3 changed files with 33 additions and 1 deletions

View file

@ -2346,7 +2346,8 @@ defmodule AshPhoenix.Form do
end
defp do_value(%{source: %Ash.Changeset{} = changeset} = form, field) do
with :error <- get_changing_value(changeset, field),
with :error <- get_invalid_value(changeset, field),
:error <- get_changing_value(changeset, field),
:error <- Ash.Changeset.fetch_argument(changeset, field),
:error <- get_non_attribute_non_argument_param(changeset, form, field),
:error <- Map.fetch(changeset.data, field) do
@ -2378,6 +2379,26 @@ defmodule AshPhoenix.Form do
end
end
defp get_invalid_value(changeset, field) when is_atom(field) do
if field in changeset.invalid_keys do
with :error <- Map.fetch(changeset.params, field) do
Map.fetch(changeset.params, to_string(field))
end
else
:error
end
end
defp get_invalid_value(changeset, field) when is_binary(field) do
if Enum.any?(changeset.invalid_keys, &(to_string(&1) == field)) do
with :error <- Map.fetch(changeset.params, field) do
Map.fetch(changeset.params, to_string(field))
end
else
:error
end
end
defp get_changing_value(changeset, field) do
Map.fetch(changeset.attributes, field)
end

View file

@ -167,6 +167,16 @@ defmodule AshPhoenix.FormTest do
assert AshPhoenix.Form.value(form, :password) == "fo"
end
test "lists with invalid values return those invalid values when getting them" do
form =
Post
|> Form.for_create(:create_author_required, api: Api, forms: [auto?: true])
|> Form.validate(%{"list_of_ints" => %{"0" => %{"map" => "of stuff"}}})
# TODO: this might be wrong
assert AshPhoenix.Form.value(form, :list_of_ints) == %{"0" => %{"map" => "of stuff"}}
end
end
describe "form_for fields" do

View file

@ -11,6 +11,7 @@ defmodule AshPhoenix.Test.Post do
attribute(:text, :string, allow_nil?: false)
attribute(:union, AshPhoenix.Test.UnionValue)
attribute(:union_array, {:array, AshPhoenix.Test.UnionValue})
attribute(:list_of_ints, {:array, :integer})
attribute(:title, :string)
end