View Source Drops.Type (drops v0.2.1)

Type behaviour and definition macros.

Summary

Functions

Define a custom map type.

Functions

Link to this macro

__using__(spec)

View Source (since 0.2.0) (macro)

Define a custom map type.

Basic primitive type

defmodule Email do
  use Drops.Type, string()
end

iex> defmodule UserContract do
...>   use Drops.Contract
...>
...>   schema do
...>     %{
...>       required(:email) => Email
...>     }
...>   end
...> end
iex> UserContract.conform(%{email: "jane@doe.org"})
{:ok, %{email: "jane@doe.org"}}
iex> {:error, errors} = UserContract.conform(%{email: 1})
{:error,
 [
   %Drops.Validator.Messages.Error.Type{
     path: [:email],
     text: "must be a string",
     meta: [predicate: :type?, args: [:string, 1]]
   }
 ]}
iex> Enum.map(errors, &to_string/1)
["email must be a string"]

Constrained primitive type

defmodule FilledEmail do
  use Drops.Type, string(:filled?)
end

iex> defmodule UserContract do
...>   use Drops.Contract
...>
...>   schema do
...>     %{
...>       required(:email) => FilledEmail
...>     }
...>   end
...> end
iex> UserContract.conform(%{email: "jane@doe.org"})
{:ok, %{email: "jane@doe.org"}}
iex> {:error, errors} = UserContract.conform(%{email: ""})
{:error,
 [
   %Drops.Validator.Messages.Error.Type{
     path: [:email],
     text: "must be filled",
     meta: [predicate: :filled?, args: [""]]
   }
 ]}
iex> Enum.map(errors, &to_string/1)
["email must be filled"]

Custom map

defmodule User do
  use Drops.Type, %{
    required(:name) => string(),
    required(:email) => string()
  }
end

iex> defmodule AccountContract do
...>   use Drops.Contract
...>
...>   schema do
...>     %{
...>       required(:user) => User
...>     }
...>   end
...> end
iex> AccountContract.conform(%{user: %{name: "Jane", email: "janedoe.org"}})
{:ok, %{user: %{name: "Jane", email: "janedoe.org"}}}
iex> {:error, errors} = AccountContract.conform(%{user: %{name: "Jane", email: 1}})
{:error,
 [
   %Drops.Validator.Messages.Error.Type{
     path: [:user, :email],
     text: "must be a string",
     meta: [predicate: :type?, args: [:string, 1]]
   }
 ]}
iex> Enum.map(errors, &to_string/1)
["user.email must be a string"]

Custom union

defmodule Price do
  use Drops.Type, union([:integer, :float], gt?: 0)
end

iex> defmodule ProductContract do
...>   use Drops.Contract
...>
...>   schema do
...>     %{
...>       required(:unit_price) => Price
...>     }
...>   end
...> end
iex> ProductContract.conform(%{unit_price: 1})
{:ok, %{unit_price: 1}}
iex> {:ok, %{unit_price: 1}}
{:ok, %{unit_price: 1}}
iex> ProductContract.conform(%{unit_price: 1.5})
{:ok, %{unit_price: 1.5}}
iex> {:ok, %{unit_price: 1.5}}
{:ok, %{unit_price: 1.5}}
iex> {:error, errors} = ProductContract.conform(%{unit_price: -1})
{:error,
 [
   %Drops.Validator.Messages.Error.Type{
     path: [:unit_price],
     text: "must be greater than 0",
     meta: [predicate: :gt?, args: [0, -1]]
   }
 ]}
iex> Enum.map(errors, &to_string/1)
["unit_price must be greater than 0"]