Current section
Files
Jump to
Current section
Files
lib/validator/not_equal.ex
defmodule Funx.Validator.NotEqual do
@moduledoc """
Validates that a value is not equal to a given reference value using an `Eq`
comparator.
`NotEqual` enforces an inequality constraint of the form:
"value must not equal X".
Equality is defined by an `Eq` instance, not by structural equality.
Options
- `:value` (required)
The reference value to compare against.
- `:eq` (optional)
An equality comparator. Defaults to `Funx.Eq.Protocol`.
- `:message` (optional)
A custom error message callback `(value -> String.t())` used to override the
default error message on failure.
Semantics
- If the value does not equal the reference value under the given `Eq`,
validation succeeds.
- If the value equals the reference value, validation fails.
- `Nothing` values are preserved and treated as not applicable.
- `Just` values are unwrapped before comparison.
"""
@behaviour Funx.Validate.Behaviour
alias Funx.Eq
alias Funx.Monad.Either
alias Funx.Monad.Maybe.{Just, Nothing}
alias Funx.Validator
# Convenience overload for default opts (raises on missing required options)
def validate(value) do
validate(value, [])
end
# Convenience overload
def validate(value, opts) when is_list(opts) do
validate(value, opts, %{})
end
@impl true
def validate(value, opts, env)
def validate(%Nothing{} = value, _opts, _env) do
Either.right(value)
end
def validate(%Just{value: value}, opts, _env) do
validate_value(value, opts)
end
def validate(value, opts, _env) do
validate_value(value, opts)
end
defp validate_value(value, opts) do
reference = Keyword.fetch!(opts, :value)
eq = Keyword.get(opts, :eq, Eq.Protocol)
Either.lift_predicate(
value,
fn v -> Eq.not_eq?(v, reference, eq) end,
fn v ->
Validator.validation_error(opts, v, "must not be equal to #{inspect(reference)}")
end
)
end
end