improvement: support zero argument functions in compare/2

This commit is contained in:
Zach Daniel 2022-10-02 20:46:30 -04:00
parent 329dfed138
commit c53eae58cd
2 changed files with 20 additions and 9 deletions

View file

@ -97,6 +97,8 @@ defmodule Ash.Resource.Validation.Builtins do
@numericality_docs """ @numericality_docs """
Validates that an attribute or argument meets the given comparison criteria. Validates that an attribute or argument meets the given comparison criteria.
The values provided for each option may be a literal value, attribute, argument, or a zero argument function.
## Options ## Options
#{Spark.OptionsHelpers.docs(Keyword.delete(Ash.Resource.Validation.Compare.opt_schema(), :attribute))} #{Spark.OptionsHelpers.docs(Keyword.delete(Ash.Resource.Validation.Compare.opt_schema(), :attribute))}

View file

@ -12,22 +12,22 @@ defmodule Ash.Resource.Validation.Compare do
doc: "The attribute to check" doc: "The attribute to check"
], ],
greater_than: [ greater_than: [
type: {:or, [:integer, :atom]}, type: {:or, [:integer, :atom, {:fun, 0}]},
required: false, required: false,
doc: "The value that the attribute should be greater than" doc: "The value that the attribute should be greater than."
], ],
greater_than_or_equal_to: [ greater_than_or_equal_to: [
type: {:or, [:integer, :atom]}, type: {:or, [:integer, :atom, {:fun, 0}]},
required: false, required: false,
doc: "The value that the attribute should be greater than or equal to" doc: "The value that the attribute should be greater than or equal to"
], ],
less_than: [ less_than: [
type: {:or, [:integer, :atom]}, type: {:or, [:integer, :atom, {:fun, 0}]},
required: false, required: false,
doc: "The value that the attribute should be less than" doc: "The value that the attribute should be less than"
], ],
less_than_or_equal_to: [ less_than_or_equal_to: [
type: {:or, [:integer, :atom]}, type: {:or, [:integer, :atom, {:fun, 0}]},
required: false, required: false,
doc: "The value that the attribute should be less than or equal to" doc: "The value that the attribute should be less than or equal to"
] ]
@ -63,7 +63,7 @@ defmodule Ash.Resource.Validation.Compare do
{:greater_than, attribute} -> {:greater_than, attribute} ->
if Comp.greater_than?(value, attribute_value(changeset, attribute)), if Comp.greater_than?(value, attribute_value(changeset, attribute)),
do: :ok, do: :ok,
else: invalid_attribute_error(opts, "must be greater than #{attribute}") else: invalid_attribute_error(opts, "must be greater than %{value}")
{:greater_than_or_equal_to, attribute} -> {:greater_than_or_equal_to, attribute} ->
if Comp.greater_or_equal?(value, attribute_value(changeset, attribute)), if Comp.greater_or_equal?(value, attribute_value(changeset, attribute)),
@ -71,13 +71,13 @@ defmodule Ash.Resource.Validation.Compare do
else: else:
invalid_attribute_error( invalid_attribute_error(
opts, opts,
"must be greater than or equal to #{attribute}" "must be greater than or equal to %{value}"
) )
{:less_than, attribute} -> {:less_than, attribute} ->
if Comp.less_than?(value, attribute_value(changeset, attribute)), if Comp.less_than?(value, attribute_value(changeset, attribute)),
do: :ok, do: :ok,
else: invalid_attribute_error(opts, "must be less than #{attribute}") else: invalid_attribute_error(opts, "must be less than %{value}")
{:less_than_or_equal_to, attribute} -> {:less_than_or_equal_to, attribute} ->
if Comp.less_or_equal?(value, attribute_value(changeset, attribute)), if Comp.less_or_equal?(value, attribute_value(changeset, attribute)),
@ -85,7 +85,7 @@ defmodule Ash.Resource.Validation.Compare do
else: else:
invalid_attribute_error( invalid_attribute_error(
opts, opts,
"must be less than or equal to #{attribute}" "must be less than or equal to %{value}"
) )
true -> true ->
@ -99,6 +99,10 @@ defmodule Ash.Resource.Validation.Compare do
end end
end end
defp attribute_value(_changeset, attribute) when is_function(attribute, 0) do
attribute.()
end
defp attribute_value(changeset, attribute) when is_atom(attribute), defp attribute_value(changeset, attribute) when is_atom(attribute),
do: Ash.Changeset.get_argument_or_attribute(changeset, attribute) do: Ash.Changeset.get_argument_or_attribute(changeset, attribute)
@ -110,6 +114,11 @@ defmodule Ash.Resource.Validation.Compare do
field: opts[:attribute], field: opts[:attribute],
message: opts[:message] || message, message: opts[:message] || message,
vars: [ vars: [
value:
case opts[:attribute] do
fun when is_function(fun, 0) -> fun.()
v -> v
end,
greater_than: opts[:greater_than], greater_than: opts[:greater_than],
less_than: opts[:less_than], less_than: opts[:less_than],
greater_than_or_equal_to: opts[:greater_than_or_equal_to], greater_than_or_equal_to: opts[:greater_than_or_equal_to],