View Source Valdi

Build Status Coverage Status Hex Version docs

Data validation for Elixir

Installation

The package can be installed by adding valdi to your list of dependencies in mix.exs:

def deps do
  [
    {:valdi, "~> 0.5.0"}
  ]
end

Document can be found at https://hexdocs.pm/valdi.

Features

Some helpers function to do validate data

  • Validate type
  • validate inclusion/exclusion
  • validate length for string and enumerable types
  • validate number
  • validate string format/pattern
  • validate custom function
  • validate required(not nil) or not
  • validate decimal (thanks @madclaws)

Usage

  • Each of these validations can be used separatedly
iex(2)>   Valdi.validate_type(10, :integer)
:ok
iex(3)>   Valdi.validate_type(10, :string)
{:error, "is not a string"}
iex(3)>   Valdi.validate_number(9, [min: 10, max: 20])
{:error, "must be greater than or equal to 10"}
  • Or you can combine multiple condition at one
iex(12)> Valdi.validate(10, type: :integer, number: [min: 10, max: 20])
:ok
iex(13)> Valdi.validate("email@g.c", type: :string, format: ~r/.+@.+\.[a-z]{2,10}/)
{:error, "format not matched"}
  • You can validate list of value
iex(51)> Valdi.validate_list([1,2,3], type: :integer, number: [min: 2])
{:error, [[0, "must be greater than or equal to 2"]]}
  • And validate map data too
    iex(54)>  validation_spec = %{
    ...(54)>     email: [type: :string],
    ...(54)>     password: [type: :string, length: [min: 8]],
    ...(54)>     age: [type: :integer, number: [min: 16, max: 60]]
    ...(54)>   }
    iex(56)> Valdi.validate_map(%{name: "dzung", password: "123456", emal: "ddd@example.com", age: 28}, validation_spec)
    {:error, %{password: "length must be greater than or equal to 8"}}

Supported validations

Type validation for built-in types and collection:

  • :boolean
  • :integer
  • :float
  • :number(int or float)
  • :string, :binary(string is binary alias)
  • :tuple
  • :array, :list
  • :atom
  • :function
  • :map
  • :date
  • :time
  • :datetime
  • :naive_datetime
  • :utc_datetime
  • {:array, type} array of item similar to Ecto.Schema
  • :keyword
  • struct for example: User. it's the struct module name
iex(11)> Valdi.validate(["one", "two", "three"],  type: {:array, :string})
:ok
iex(12)> Valdi.validate(["one", "two", "three"],  type: :array)
:ok
iex(13)> Valdi.validate(["one", "two", "three"],  type: :map)
{:error, "is not a map"}
iex(14)>

Validate required Validate value if value is not nil. This function can receive a function to dynamicall calculate required or not.

  iex(1)> Magik.Validator.validate_required(nil, true)
  {:error, "is required"}
  iex(2)> Magik.Validator.validate_required(1, true)
  :ok
  iex(3)> Magik.Validator.validate_required(nil, false)
  :ok
  iex(4)> Magik.Validator.validate_required(nil, fn -> 2 == 2 end)
  {:error, "is required"}

Validate inclusion and exclusion

iex(15)> Valdi.validate("one", in: ~w(one two three))
:ok
iex(16)> Valdi.validate("five", in: ~w(one two three))
{:error, "not be in the inclusion list"}
iex(17)> Valdi.validate("five", not_in: ~w(one two three))
:ok

Validate format/regex

iex(13)> Valdi.validate("email@g.c", type: :string, format: ~r/.+@.+\.[a-z]{2,10}/)
{:error, "format not matched"}
iex(18)> Valdi.validate("123", format: ~r/\d{3}/)
:ok

Validate number

Here are list of check condition on number value:

  • equal_to
  • greater_than_or_equal_to | min

  • greater_than
  • less_than
  • less_than_or_equal_to | max

iex(19)> Valdi.validate(12, number: [greater_than: 0, less_than: 20])
:ok
iex(20)> Valdi.validate(12, number: [min: 0, max: 10])
{:error, "must be less than or equal to 10"}
iex(21)> Valdi.validate(12, number: [equal_to: 10])
{:error, "must be equal to 10"}
iex(22)>

Validate decimal Similar to validate number

iex(19)> Valdi.validate(Decimal.new("10.0"), decimal: [greater_than: Decimal.new("0.0"), less_than: Decimal.new("20.0")])
:ok

Validate string and enumerable length

Valdi supported check length for map, list, binary, tuple All check conditions are the same with number validation

iex(24)> Valdi.validate("mypassword", length: [min: 8, max: 16])
:ok
iex(25)> Valdi.validate([1, 2, 3], length: [min: 3])
:ok
iex(26)> Valdi.validate({"one", "two"}, length: [min: 3])
{:error, "length must be greater than or equal to 3"}
iex(27)> Valdi.validate(50, length: [min: 2])
{:error, "length check supports only lists, binaries, maps and tuples"}

Custom validation function

You can pass your validation function too. You function must follow spec:

func(any()):: :ok | {:error, message::String.t()}
iex(32)> Valdi.validate(12, func: fn val -> if is_binary(val), do: :ok, else: {:error, "not a string"} end)
{:error, "not a string"}

Validate each array element Support all above validator to validate each array element

iex(32)> Valdi.validate([1, 10, 20], each: [number: [min: 10]])

{:error, [[0, "must be greater than or equal to 10"]]}