Litmus
Data validation in Elixir
Installation
If available in Hex, the package can be installed
by adding litmus
to your list of dependencies in mix.exs
:
def deps do
[
{:litmus, "~> 0.1.0"}
]
end
Usage
Litmus validates data against a predefined schema with the Litmus.validate/2
function.
If the data is valid, the function returns {:ok, data}
. The data returned will be coerced according to the schema defined.
If the data passed does not follow the rules defined in the schema, the function returns {:error, error_message}
. It will also return an error when receiving a field that has not been specified in the provided schema.
iex> schema = %{
...> "id" => %Litmus.Type.Any{required: true},
...> "username" => %Litmus.Type.String{
...> min_length: 6,
...> required: true
...> },
...> "pin" => %Litmus.Type.Number{
...> min: 1000,
...> max: 9999,
...> required: true
...> },
...> "new_user" => %Litmus.Type.Boolean{
...> truthy: ["1"],
...> falsy: ["0"]
...> }
...> }
iex> params = %{"id" => 1, "username" => "user@123", "pin" => 1234, "new_user" => "1"}
iex> Litmus.validate(params, schema)
{:ok, %{"id" => 1, "new_user" => true, "pin" => 1234, "username" => "user@123"}}
iex> schema = %{"id" => %Litmus.Type.Any{}}
iex> params = %{"password" => 1}
iex> Litmus.validate(params, schema)
{:error, "password is not allowed"}
Currently, we support the following data types:
Data Types Supported
Litmus.Type.Any
The Any
module contains options that will be common to all data types. It supports the following options:
:required
- Settingrequired
totrue
will cause a validation error when a field is not present or the value isnil
. Allowed values for required aretrue
andfalse
. The default isfalse
.
iex> schema = %{"id" => %Litmus.Type.Any{required: true}}
iex> params = %{"id" => 1}
iex> Litmus.validate(params, schema)
{:ok, %{"id" => 1}}
iex> params = %{}
iex> Litmus.validate(params, schema)
{:error, "id is required"}
Litmus.Type.Boolean
The Boolean
module contains options that will validate Boolean data types. It converts truthy and falsy values to true
or false
. It supports the following options:
:truthy
- Allows additional values, i.e. truthy values to be considered valid booleans by converting them totrue
during validation. Allowed value is an array of strings, number or boolean values. The default is[true, "true"]
:falsy
- Allows additional values, i.e. falsy values to be considered valid booleans by converting them tofalse
during validation. Allowed value is an array of strings, number or boolean values. The default is[false, "false"]
iex> schema = %{
...> "new_user" => %Litmus.Type.Boolean{
...> truthy: ["1"],
...> falsy: ["0"]
...> }
...> }
iex> params = %{"new_user" => "1"}
iex> Litmus.validate(params, schema)
{:ok, %{"new_user" => true}}
iex> params = %{"new_user" => 0}
iex> Litmus.validate(params, schema)
{:error, "new_user must be a boolean"}
Litmus.Type.Number
The Number
module contains options that will validate Number data types. It converts “stringified” numerical values to numbers. It supports the following options:
:min
- Specifies the minimum value of the field.:max
- Specifies the maximum value of the field.:integer
- Specifies that the number must be an integer (no floating point). Allowed values aretrue
andfalse
. The default isfalse
.
iex> schema = %{
...> "id" => %Litmus.Type.Number{
...> integer: true
...> },
...> "gpa" => %Litmus.Type.Number{
...> min: 0,
...> max: 4
...> }
...> }
iex> params = %{"id" => "123", "gpa" => 3.8}
iex> Litmus.validate(params, schema)
{:ok, %{"id" => 123, "gpa" => 3.8}}
iex> params = %{"id" => "123.456", "gpa" => 3.8}
iex> Litmus.validate(params, schema)
{:error, "id must be an integer"}
Litmus.Type.String
The String
module contains options that will validate String data types. It converts boolean and number values to strings. It will also convert nil
value to empty string. It supports the following options:
:min_length
- Specifies the minimum number of characters needed in the string. Allowed values are non-negative integers.:max_length
- Specifies the maximum number of characters needed in the string. Allowed values are non-negative integers.:length
- Specifies the exact number of characters needed in the string. Allowed values are non-negative integers.:regex
- Specifies a Regular expression that a string must match. Allowed value is a struct consisting ofpattern
anderror_message
, wherepattern
is aRegex
anderror_message
is aString.t()
value. Default value for pattern isnil
. If no error_message is given, the default message returned on error is"#{field} must be in a valid format"
.:trim
- Removes additional whitespaces in a string and returns the new value. Allowed values aretrue
andfalse
. The default isfalse
.
iex> schema = %{
...> "username" => %Litmus.Type.String{
...> min_length: 3,
...> max_length: 10,
...> trim: true
...> },
...> "password" => %Litmus.Type.String{
...> length: 6,
...> regex: %Litmus.Type.String.Regex{
...> pattern: ~r/^[a-zA-Z0-9_]*$/,
...> error_message: "password must be alphanumeric"
...> }
...> }
...> }
iex> params = %{"username" => " user123 ", "password" => "root01"}
iex> Litmus.validate(params, schema)
{:ok, %{"username" => "user123", "password" => "root01"}}
iex> params = %{"username" => " user123 ", "password" => "ro!_@1"}
iex> Litmus.validate(params, schema)
{:error, "password must be alphanumeric"}
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/litmus.