Server-side validation for parsed number values.
Pure Elixir, no Ecto dependency. The Ecto changeset bridge is
in Localize.Inputs.Number.Changeset.
Summary
Functions
Validates a parsed number against bounds, precision, and required-ness.
Validates a unit-of-measure form submission.
Functions
@spec validate_number(term(), Keyword.t()) :: :ok | {:error, Localize.Inputs.ValidationError.t()}
Validates a parsed number against bounds, precision, and required-ness.
Arguments
valueis aDecimal, integer, ornil.optionsis a keyword list of options.
Options
:required— whentrue,nilis rejected.:min— minimum allowed value (any numeric form the parser accepts).:max— maximum allowed value.:decimals— maximum number of fractional digits.
Returns
:okwhen every check passes.{:error, %Localize.Inputs.ValidationError{errors: [{atom(), String.t()}]}}with one entry per failing check, in the order:required,:min,:max,:decimals.Localize.Inputs.Number.Changeset.validate_number/3unpacks the entries into per-field changeset errors.
Examples
iex> Localize.Inputs.Number.Validator.validate_number(Decimal.new("5"), min: 1, max: 10)
:ok
iex> {:error, %Localize.Inputs.ValidationError{errors: errors}} =
...> Localize.Inputs.Number.Validator.validate_number(Decimal.new("15"), max: 10)
iex> errors
[{:max, "must be at most 10"}]
iex> {:error, %Localize.Inputs.ValidationError{errors: errors}} =
...> Localize.Inputs.Number.Validator.validate_number(nil, required: true)
iex> errors
[{:required, "is required"}]
@spec validate_unit(term(), Keyword.t()) :: :ok | {:error, Localize.Inputs.ValidationError.t()}
Validates a unit-of-measure form submission.
Accepts the %{"amount" => ..., "unit" => ...} map shape that
Localize.Inputs.Number.Components.unit_input/1 submits. Checks that
the amount passes validate_number/2 and that the unit is a
known unit in the given category.
Arguments
value— a%{"amount", "unit"}map (string or atom keys), a bare numeric value,nil, or"".optionsis a keyword list of options.
Options
:category— the unit category as a string (e.g."length"). Required. The submitted unit is checked againstLocalize.Inputs.Number.Unit.all_unit_names/2.:required— whentrue,nilamount is rejected.:min,:max,:decimals— forwarded tovalidate_number/2.
Returns
:okon success.{:error, ValidationError.t()}on any failure — combined amount-validation errors plus a{:unit, "..."}error if the unit is missing or not in the category.
Examples
iex> Localize.Inputs.Number.Validator.validate_unit(
...> %{"amount" => Decimal.new("1.75"), "unit" => "meter"},
...> category: "length"
...> )
:ok
iex> {:error, %Localize.Inputs.ValidationError{errors: errors}} =
...> Localize.Inputs.Number.Validator.validate_unit(
...> %{"amount" => Decimal.new("1.75"), "unit" => "bogon"},
...> category: "length"
...> )
iex> Keyword.get(errors, :unit) =~ "bogon"
true
iex> {:error, %Localize.Inputs.ValidationError{errors: errors}} =
...> Localize.Inputs.Number.Validator.validate_unit(
...> %{"amount" => Decimal.new("70"), "unit" => "kilogram"},
...> category: "length"
...> )
iex> Keyword.get(errors, :unit) =~ "mass"
true