Validixir (validixir v1.2.2)

Module containing all basic functionality needed for validation.

Link to this section Summary

Functions

Takes a validation result and a function. In case of a success the function is applied to the candidate and the result is returned. In case of a failure that failure is returned unchanged.

Augments a failure's error contexts if a failure is passed, else returns the success.

Augments a failure's error messages if a failure is passed, else returns the success.

Takes a validation result and two functions that are applied as in map_success/2 and map_failure/2 respectively.

Applies a function to each of the errors of a failure. If a success is passed it is returned unchanged.

Applies a function to the candidate of a success. If a failure is passed it is returned unchanged.

Overrides a failure's error contexts if a failure is passed, else returns the success.

Overrides a failure's error messages if a failure is passed, else returns the success.

Takes a value and lifts it in a validation result, returning a success with the value as its candidate.

Applies a function wrapped in a validation success to the candidate of another validation success. If both validation results are failures it returns them combined. If only one is a failure, this failure is returned unchanged.

Takes a list of validation results and returns a success that contains the list of all candidates, if all validation results are successes. Else all failures are combined and a validation failure is returned.

Does the same as Validixir.sequence/1 but applies a validation function to all candidates first.

Takes a function that is called if all validation results are successes. The call parameters are then the candidates in the respective order. The return value of this function call is then wrapped as a success and returned.

Applies a list of validation functions to a candidate. Returns a success that contains the candidate iff each validation function returns a success. Else returns a validation failure containing errors of each failed validation.

Returns true if a value is either a Validixir.Success or a Validixir.Failure, returns false else.

Link to this section Types

Link to this type

validate_all_return_t(inner_t)

@type validate_all_return_t(inner_t) ::
  {:ok, validation_result_t(inner_t)} | {:error, :no_validators}
Link to this type

validation_fun_t(result_t)

@type validation_fun_t(result_t) :: (any() -> validation_result_t(result_t))
Link to this type

validation_result_t(inner_t)

@type validation_result_t(inner_t) ::
  Validixir.Failure.t() | Validixir.Success.t(inner_t)

A validation result is one of the following:

  • A failure
  • A success

The type represents the possible results of a validation. The type takes a parameter that sets the candidate type in case of a success.

Link to this section Functions

Link to this function

and_then(validation_result, f)

Takes a validation result and a function. In case of a success the function is applied to the candidate and the result is returned. In case of a failure that failure is returned unchanged.

This function is used to chain validations.

examples

Examples

iex> Validixir.Success.make(0) |> Validixir.and_then(fn x -> Validixir.Success.make(x + 1) end)
{:ok, 1}

iex> Validixir.Failure.make([]) |> Validixir.and_then(fn x -> x + 1 end)
{:error, %Validixir.Failure{errors: [], __message_lookup: %{}}}
Link to this function

augment_contexts(success, additional_context)

Augments a failure's error contexts if a failure is passed, else returns the success.

examples

Examples

iex> Validixir.pure(12) |> Validixir.augment_contexts(Hello)
{:ok, 12}

iex> error_1 = Validixir.Error.make(1, :message, Context)
iex> error_2 = Validixir.Error.make(2, :message, AnotherContext)
iex> failure = Validixir.Failure.make([error_1, error_2])
iex> Validixir.augment_contexts(failure, AdditionalContext)
{:error, %Validixir.Failure{
    errors: [
        %Validixir.Error{candidate: 1, message: :message, context: [ AdditionalContext, Context ]},
        %Validixir.Error{candidate: 2, message: :message, context: [ AdditionalContext, AnotherContext ]},
    ],
    __message_lookup: %{message: true}
}}
Link to this function

augment_messages(success, additional_message)

Augments a failure's error messages if a failure is passed, else returns the success.

examples

Examples

iex> Validixir.pure(12) |> Validixir.augment_messages(Hello)
{:ok, 12}

iex> error_1 = Validixir.Error.make(1, :message, Context)
iex> error_2 = Validixir.Error.make(2, :another_message, Context)
iex> failure = Validixir.Failure.make([error_1, error_2])
iex> Validixir.augment_messages(failure, :additional_message)
{:error, %Validixir.Failure{
    errors: [
        %Validixir.Error{candidate: 1, message: [:additional_message, :message], context: Context},
        %Validixir.Error{candidate: 2, message: [:additional_message, :another_message], context: Context}
    ],
    __message_lookup: %{[:additional_message, :message] => true, [:additional_message, :another_message] => true, :additional_message => true, :message => true, :another_message => true}
}}
Link to this function

failure_from_error(candidate, message, context)

See Validixir.Failure.make_from_error/3.

Link to this function

map(failure, f_success, f_failure)

Takes a validation result and two functions that are applied as in map_success/2 and map_failure/2 respectively.

examples

Examples

iex> success = Validixir.Success.make(0)
iex> Validixir.map(success, fn a -> a + 1 end, fn _ -> :does_nothing end)
{:ok, 1}

iex> failure = Validixir.Failure.make([Validixir.Error.make(1, :hello, :hello)])
iex> Validixir.map(failure, fn _ -> :does_nothing end, fn err -> %Validixir.Error{ err | candidate: 2} end)
{:error, %Validixir.Failure{errors: [Validixir.Error.make(2, :hello, :hello)], __message_lookup: %{hello: true}}}
Link to this function

map_failure(failure, f)

Applies a function to each of the errors of a failure. If a success is passed it is returned unchanged.

examples

Examples

iex> success = Validixir.Success.make(0)
iex> Validixir.map_failure(success, fn a -> a + 1 end)
{:ok, 0}

iex> failure = Validixir.Failure.make([Validixir.Error.make(1, :hello, :hello)])
iex> Validixir.map_failure(failure, fn err -> %Validixir.Error{ err | candidate: 2} end)
{:error, %Validixir.Failure{errors: [Validixir.Error.make(2, :hello, :hello)], __message_lookup: %{hello: true}}}
Link to this function

map_success(success, f)

Applies a function to the candidate of a success. If a failure is passed it is returned unchanged.

examples

Examples

iex> success = Validixir.Success.make(0)
iex> Validixir.map_success(success, fn a -> a + 1 end)
{:ok, 1}

iex> failure = Validixir.Failure.make([])
iex> Validixir.map_success(failure, fn a -> a + 1 end)
{:error, %Validixir.Failure{errors: [], __message_lookup: %{}}}
Link to this function

override_contexts(success, context)

Overrides a failure's error contexts if a failure is passed, else returns the success.

examples

Examples

iex> Validixir.pure(12) |> Validixir.override_contexts(Hello)
{:ok, 12}

iex> error_1 = Validixir.Error.make(1, :message, Context)
iex> error_2 = Validixir.Error.make(2, :another_message, Context)
iex> failure = Validixir.Failure.make([error_1, error_2])
iex> Validixir.override_contexts(failure, NewContext)
{:error, %Validixir.Failure{
    errors: [
      %Validixir.Error{candidate: 1, message: :message, context: NewContext},
      %Validixir.Error{candidate: 2, message: :another_message, context: NewContext}
    ],
    __message_lookup: %{another_message: true, message: true}
}}
Link to this function

override_messages(success, message)

Overrides a failure's error messages if a failure is passed, else returns the success.

examples

Examples

iex> Validixir.pure(12) |> Validixir.override_messages(Hello)
{:ok, 12}

iex> error_1 = Validixir.Error.make(1, :message, Context)
iex> error_2 = Validixir.Error.make(2, :another_message, Context)
iex> failure = Validixir.Failure.make([error_1, error_2])
iex> Validixir.override_messages(failure, :additional_message)
{:error, %Validixir.Failure{
    errors: [
        %Validixir.Error{candidate: 1, message: :additional_message, context: Context},
        %Validixir.Error{candidate: 2, message: :additional_message, context: Context}
    ],
    __message_lookup: %{additional_message: true}
}}

Takes a value and lifts it in a validation result, returning a success with the value as its candidate.

examples

Examples

iex> Validixir.pure(12)
{:ok, 12}

Applies a function wrapped in a validation success to the candidate of another validation success. If both validation results are failures it returns them combined. If only one is a failure, this failure is returned unchanged.

This function is key in implementing applicatives.

examples

Examples

iex> s1 = Validixir.Success.make(fn a -> a + 1 end)
iex> s2 = Validixir.Success.make(0)
iex> Validixir.seq(s1, s2)
{:ok, 1}

iex> error = Validixir.Error.make(:hello, "not allowed", nil)
iex> failure = Validixir.Failure.make([error])
iex> success = Validixir.Success.make(1)
iex> Validixir.seq(failure, success)
{:error, %Validixir.Failure{errors: [error], __message_lookup: %{"not allowed" => true}}}

iex> error1 = Validixir.Error.make(:hello, "not allowed", nil)
iex> error2 = Validixir.Error.make(:world, "not allowed", nil)
iex> failure1 = Validixir.Failure.make([error1])
iex> failure2 = Validixir.Failure.make([error2])
iex> Validixir.seq(failure1, failure2)
{:error, %Validixir.Failure{errors: [error1, error2], __message_lookup: %{"not allowed" => true}}}

Takes a list of validation results and returns a success that contains the list of all candidates, if all validation results are successes. Else all failures are combined and a validation failure is returned.

examples

Examples

iex> Validixir.sequence([Validixir.Success.make(1), Validixir.Success.make(2)])
{:ok, [1,2]}

iex> error1 = Validixir.Error.make(:hello, "not allowed", nil)
iex> error2 = Validixir.Error.make(:world, "not allowed", nil)
iex> failure1 = Validixir.Failure.make([error1])
iex> failure2 = Validixir.Failure.make([error2])
iex> Validixir.sequence([failure1, failure2])
{:error, %Validixir.Failure{errors: [error1, error2], __message_lookup: %{"not allowed" => true}}}
Link to this function

sequence_of(candidates, validation_f)

Does the same as Validixir.sequence/1 but applies a validation function to all candidates first.

examples

Examples

iex> success_fn = fn c -> Validixir.Success.make(c) end
iex> Validixir.sequence_of([1, 2], success_fn)
{:ok, [1,2]}

iex> failure_fn = fn c -> [Validixir.Error.make(c, "not allowed", nil)] |> Validixir.Failure.make() end
iex> Validixir.sequence_of([:hello, :world], failure_fn)
{:error, %Validixir.Failure{
    errors: [Validixir.Error.make(:hello, [{:index, 0}, "not allowed"], nil),
             Validixir.Error.make(:world, [{:index, 1}, "not allowed"], nil)],
    __message_lookup: %{"not allowed" => true, [{:index, 0}, "not allowed"] => true, [{:index, 1}, "not allowed"] => true, {:index, 0} => true, {:index, 1} => true}}}

Same as pure/1.

examples

Examples

iex> Validixir.success(12)
{:ok, 12}
Link to this function

validate(result_f, validations)

@spec validate(function(), [validation_result_t(any())]) :: validation_result_t(any())

Takes a function that is called if all validation results are successes. The call parameters are then the candidates in the respective order. The return value of this function call is then wrapped as a success and returned.

If there is at least one failure, errors get accumulated and a validation failure is returned.

examples

Examples

iex> Validixir.validate(fn a, b -> {a, b} end, [Validixir.Success.make(1), Validixir.Success.make(2)])
{:ok, {1,2}}

iex> error1 = Validixir.Error.make(:hello, "not allowed", nil)
iex> error2 = Validixir.Error.make(:world, "not allowed", nil)
iex> failure1 = Validixir.Failure.make([error1])
iex> failure2 = Validixir.Failure.make([error2])
iex> Validixir.validate(fn a, b -> {a, b} end, [failure1, failure2])
{:error, %Validixir.Failure{errors: [error1, error2], __message_lookup: %{"not allowed" => true}}}
Link to this function

validate_all(validation_fs, candidate)

Applies a list of validation functions to a candidate. Returns a success that contains the candidate iff each validation function returns a success. Else returns a validation failure containing errors of each failed validation.

examples

Examples

iex> success_fn_1 = fn c -> Validixir.Success.make(c) end
iex> success_fn_2 = fn _ -> Validixir.Success.make(12) end
iex> Validixir.validate_all([success_fn_1, success_fn_2], 1)
{:ok, 1}

iex> failure_fn = fn c -> [Validixir.Error.make(c, "not allowed", nil)] |> Validixir.Failure.make() end
iex> success_fn = fn _ -> Validixir.Success.make(12) end
iex> Validixir.validate_all([failure_fn, success_fn], :hello)
{:error, %Validixir.Failure{errors: [Validixir.Error.make(:hello, [ {:index, 0}, "not allowed" ], nil)], __message_lookup: %{"not allowed" => true, [{:index, 0}, "not allowed"] => true, {:index, 0} => true}}}
Link to this function

validation_result?(thing)

@spec validation_result?(any()) :: boolean()

Returns true if a value is either a Validixir.Success or a Validixir.Failure, returns false else.

examples

Examples

iex> Validixir.validation_result?(Validixir.Success.make(12))
true

iex> Validixir.validation_result?(Validixir.Failure.make([]))
true

iex> Validixir.validation_result?(%{})
false

iex> {:error, internal_failure} = Validixir.Failure.make([])
iex> Validixir.validation_result?(internal_failure)