DEV Community

Cover image for Easy data validation with with Valdi in Elixir
Dung Nguyen for OnPoint Vietnam

Posted on • Updated on

Easy data validation with with Valdi in Elixir

Credit: this icon is from flaticon.com

In previous article, I shown you how to implement you own validation module. I you haven't read it, you can find it here How to build an Elixir validator from scratch

And I think some of you may want a ready to use library so I wrapped it up, added some useful api and published on hex.pm and github repo here.

This post is just showcases of what it can do. (not too much fancy)
First, add dependencies to your mix.exs and you are ready to go.

{:valdi, "~> 0.2.0"}
Enter fullscreen mode Exit fullscreen mode

And this is how it works.

Validate using a specific validation function

iex(1)> age = 20
20
iex(2)> Valdi.validate_number(age, min: 18, max: 60)
:ok
Enter fullscreen mode Exit fullscreen mode

But most of the time you don't do this, you will want to combine multiple validations at a time.

iex(4)> Valdi.validate("20", type: :integer,  number: [min: 18, max: 60])
{:error, "is not a integer"}
Enter fullscreen mode Exit fullscreen mode

And you may want to validate a list of value too:

iex(1)> Valdi.validate_list(["hi", "how", "are", "you", 100], type: :string,  length: [min: 3])
{:error,
 [[0, "length must be greater than or equal to 3"], [4, "is not a string"]]}
Enter fullscreen mode Exit fullscreen mode

If validation failed, you got a list of error and index of error item.

Valdi supports you to validate a simple map with given specification:

product_spec = %{
    name: [type: :string, required: true],
    sku: [type: :string, required: true],
    price: [type: :integer, number: [min: 0]]
}
Valdi.validate_map(%{
    name: "A magic pen",
    sku: nil,
    price: -1
}, product_spec)

# {:error, %{price: "must be greater than or equal to 0", sku: "is required"}}
Enter fullscreen mode Exit fullscreen mode

Valdi does not support nested map validation.

You might want to take a look at Contrak, it extended Valdi by providing a simple way to define and validate nested schema.

Why I didn't put those in just one library? I think data validation and schema validation are quite different, so I want to keep libraries simple and do its best thing.

Here you can define your own validation

Valdi.validate("as008x8234", type: :string, func: fn value ->
   if String.match?(value, ~r/^\d{4}$/), do: :ok, else: {:error, "not a year string"}
end)

# {:error, "not a year string"}
Enter fullscreen mode Exit fullscreen mode

Hope this small library can help. If you have any suggestion please comment.
Thank you.

Discussion (0)