Skip to content

Instantly share code, notes, and snippets.

@fvumbaca
Last active April 10, 2019 17:23
Show Gist options
  • Save fvumbaca/5c65af2312cee3964263c4d98ed3242d to your computer and use it in GitHub Desktop.
Save fvumbaca/5c65af2312cee3964263c4d98ed3242d to your computer and use it in GitHub Desktop.
Simple Map Validator in Elixir
defmodule MyApp.Validator do
@type validator :: :string | :required
@type schema :: %{any() => validator | [validator]}
@spec validate(map(), schema) :: {:ok, any()} | {:validation_error, [String.t()]}
def validate(input, schema) do
schema
|> Enum.reduce([], fn {key, val}, errors ->
input
|> Map.get(key, {__MODULE__, :no_value_found})
|> validate_term(val)
|> case do
{:ok, _} -> errors
{:error, error} -> ["#{key} #{error}" | errors]
end
end)
|> case do
[] ->
{:ok, input}
errors ->
{:validation_error, errors}
end
end
# Helpers
@spec validate_term(any(), validator | [validator]) :: {:ok, any()} | {:error, String.t()}
def validate_term(term, constraint_list) when is_list(constraint_list) do
constraint_list
|> Enum.find_value({:ok, term}, fn constraint ->
case validate_term(term, constraint) do
{:ok, ^term} -> false
{:error, message} -> {:error, message}
end
end)
end
# Required validators
def validate_term({__MODULE__, :no_value_found}, :required), do: {:error, "must be defined"}
def validate_term(term, :required), do: {:ok, term}
# String validators
def validate_term(term, :string) when is_binary(term), do: {:ok, term}
def validate_term(_term, :string), do: {:error, "must be a string"}
end
@fvumbaca
Copy link
Author

fvumbaca commented Apr 8, 2019

Nifty for phoenix endpoints:

@get_user_schema %{
  "userId" => [:required, :string],
  "token" => [:required, :string]
}
def get_user(conn, param) do
  with {:ok, _valid_params} <- MyApp.Validator.validate(param, @get_user_schema) do
  # ...
  else
    {:validation_error, formatted_errors} ->
      conn
      |> put_status(400)
      |> json(%{"ok" => false, "errors" => formatted_errors})
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment