fix: properly set error vars with list constraints

fix: when creating changesets/queries that already have arguments, revalidate arguments
This commit is contained in:
Zach Daniel 2022-10-31 14:20:13 -04:00
parent 80f67d3afc
commit 3407d1e2e3
3 changed files with 25 additions and 8 deletions

View file

@ -503,13 +503,14 @@ defmodule Ash.Changeset do
Ash.Tracer.set_metadata(opts[:tracer], :changeset, metadata)
changeset
|> Map.put(:action, action)
|> reset_arguments()
|> handle_errors(action.error_handler)
|> set_actor(opts)
|> set_authorize(opts)
|> set_tracer(opts)
|> set_tenant(opts[:tenant] || changeset.tenant)
|> Map.put(:__validated_for_action__, action.name)
|> Map.put(:action, action)
|> cast_params(action, params)
|> set_argument_defaults(action)
|> require_arguments(action)
@ -533,6 +534,14 @@ defmodule Ash.Changeset do
end
end
defp reset_arguments(%{arguments: arguments} = changeset) when is_map(arguments) do
Enum.reduce(arguments, changeset, fn {key, value}, changeset ->
set_argument(changeset, key, value)
end)
end
defp reset_arguments(changeset), do: changeset
@spec set_on_upsert(t(), list(atom)) :: Keyword.t()
def set_on_upsert(changeset, upsert_keys) do
keys = upsert_keys || Ash.Resource.Info.primary_key(changeset.resource)
@ -627,6 +636,8 @@ defmodule Ash.Changeset do
changeset =
changeset
|> Map.put(:action, action)
|> reset_arguments()
|> handle_errors(action.error_handler)
|> set_actor(opts)
|> set_authorize(opts)
@ -635,7 +646,6 @@ defmodule Ash.Changeset do
|> set_tenant(
opts[:tenant] || changeset.tenant || changeset.data.__metadata__[:tenant]
)
|> Map.put(:action, action)
|> Map.put(:__validated_for_action__, action.name)
|> cast_params(action, params || %{})
|> set_argument_defaults(action)

View file

@ -294,15 +294,14 @@ defmodule Ash.Query do
Ash.Tracer.set_metadata(opts[:tracer], :query, metadata)
query = Map.put(query, :action, action.name)
query
|> Map.put(:action, action)
|> reset_arguments()
|> timeout(query.timeout || opts[:timeout])
|> set_actor(opts)
|> set_authorize?(opts)
|> set_tracer(opts)
|> Ash.Query.set_tenant(opts[:tenant] || query.tenant)
|> Map.put(:action, action)
|> Map.put(:__validated_for_action__, action_name)
|> cast_params(action, args)
|> set_argument_defaults(action)
@ -1109,6 +1108,14 @@ defmodule Ash.Query do
end
end
defp reset_arguments(%{arguments: arguments} = query) when is_map(arguments) do
Enum.reduce(arguments, query, fn {key, value}, query ->
set_argument(query, key, value)
end)
end
defp reset_arguments(query), do: query
defp add_invalid_errors(query, argument, error) do
messages =
if Keyword.keyword?(error) do

View file

@ -516,7 +516,7 @@ defmodule Ash.Type do
case list_constraint_errors do
[] ->
nil_items? = Keyword.get(constraints, :nil_items?, true)
nil_items? = Keyword.get(constraints, :nil_items?, false)
item_constraints = constraints[:items] || []
if item_constraints != [] || !nil_items? do
@ -593,14 +593,14 @@ defmodule Ash.Type do
|> Enum.reduce([], fn
{:min_length, min_length}, errors ->
if length < min_length do
[message: "must have %{min} or more items", min: min_length]
[message: "must have %{min} or more items", vars: [min: min_length]]
else
errors
end
{:max_length, max_length}, errors ->
if length > max_length do
[message: "must have %{max} or fewer items", max: max_length]
[message: "must have %{max} or fewer items", vars: [max: max_length]]
else
errors
end