Validate

Validate incoming requests in an easy to reason-about way using Elixir.

🚨 Validate is an active WIP. Building mostly for fun/to satisfy my own needs on a project 🚨

Coming from languages like PHP and Node.js it can be difficult to reason about validating your requests using Ecto. This provides a simple data validation layer that aims to be extensible to allow for custom validation logic provided by the user.

Todo

Installation

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

def deps do
  [
    {:validate, "~> 0.2.2"}
  ]
end

Usage

defmodule MyApp.UserController do
  import Validate

  def create(conn, params) do
    case validate(params, create_rules) do
      {:ok, data} ->
        # ... create user
        # `data` is filtered to only the keys provided in `rules`

      {:error, errors} ->
        # errors is a map that matches the rules provided
        # in this case: %{ "username" => "required" }
        json(conn, errors)
    end
  end

  defp create_rules, do: %{
    "username": [:required],
  }
end

Validators

Required

Validates input is not:

import Validate
data = %{ "username" => "" }
rules = %{
  "username" => [
    :required
  ]
}
validate(data, rules)
# {:error, %{ "username" => "required" }}

Optional

Does not continue with the rest of the validators if the value is not present or nil

import Validate
data = %{}
rules = %{
  "username" => [
    :optional,
    :string,
  ]
}
# value not present, so it's ok
validate(data, rules)
# {:ok, %{}}
import Validate
data = %{ "username" => 123 }
rules = %{
  "username" => [
    :optional,
    :string,
  ]
}
# value present, so it continues on to next validators
validate(data, rules)
# {:error, %{"username" => "not a string"}}

String

Validates input is a string

import Validate
data = %{
  "username" => 123
}
rules = %{
  "username" => [
    :string,
  ]
}
validate(data, rules)
# {:error, %{"username" => "not a string"}}

Number

Validates input is a number (float or int)

import Validate
data = %{
  "balance" => "very low"
}
rules = %{
  "balance" => [
    :number,
  ]
}
validate(data, rules)
# {:error, %{"balance" => "not a number"}}

List

Validates input is a list (array)

import Validate
data = %{
  "cities" => "saskatoon"
}
rules = %{
  "cities" => [
    :list,
  ]
}
validate(data, rules)
# {:error, %{"balance" => "not a list"}}