Phoenix request params validation library.
- Reduce code boilerplate
- Shorter schema definition
- Default function which generate value each casting time
- Custom validation functions
- Custom parse functions
Available in Hex, the package can be installed
by adding skema
to your list of dependencies in mix.exs
:
def deps do
[
{:skema, "~> 0.1"}
]
end
Process order
Cast data -> validate casted data -> transform data
use Skema
defschema IndexParams do
field :keyword, :string
field :status, :string, required: true
field :group_id, :integer, number: [greater_than: 0]
field :name, :string
end
def index(conn, params) do
with {:ok, better_params} <- Skema.cast(params, IndexParams) do
# do anything with your params
else
{:error, errors} -> # return params error
end
end
use Skema
defschema IndexParams do
field :keyword, :string
field :status, :string, required: true
field :group_id, :integer, number: [greater_than: 0]
field :name, :string
end
Define a field using macro @spec field(field_name :: atom(), type :: term(), opts \\ [])
type
:Skema
support same data type asEcto
. I borrowed code from Ecto
Supported options:
default
: default value or default functioncast_func
: custom cast functionnumber, format, length, in, not_in, func, required, each
are available validationsfrom
: use value from another fieldas
: alias key you will receive fromSkema.cast
if casting is succeeded
You can define a default value for a field if it's missing from the params.
field :status, :string, default: "pending"
Or you can define a default value as a function. This function is evaluated when Skema.cast
gets invoked.
field :date, :utc_datetime, default: &Timex.now/0
You can define your own casting function, skema
provide cast_func
option.
Your cast_func
must follows this spec
fn(any) :: {:ok, any} | {:error, binary} | :error
def my_array_parser(value) do
if is_binary(value) do
ids =
String.split(value, ",")
|> Enum.map(&String.to_integer(&1))
{:ok, ids}
else
{:error, "Invalid string"
end
end
defschema Sample do
field :user_id, {:array, :integer}, cast_func: &my_array_parser/1
end
This is a demo parser function.
With Skema
you can parse and validate nested map and list easily
defschema Address do
field :street, :string
field :district, :string
field :city, :string
end
defschema User do
field :name, :string,
field :email, :string, required: true
field :addresses, {:array, Address}
end
Skema
uses Valdi
validation library. You can read more about Valdi here
Basically it supports following validation
-
validate inclusion/exclusion
-
validate length for string and enumerable types
-
validate number
-
validate string format/pattern
-
validate custom function
-
validate required(not nil) or not
-
validate each array item
defschema Product do field :sku, :string, required: true, length: [min: 6, max: 20] field :name, :string, required: true, field :quantity, :integer, number: [min: 0], field :type: :string, in: ~w(physical digital), field :expiration_date, :naive_datetime, func: &my_validation_func/1, field :tags, {:array, :string}, each: [length: [max: 50]] end
### Dynamic required
- Can accept function or `{module, function}` tuple
- Only support 2 arity function
```elixir
def require_email?(value, data), do: is_nil(email.phone)
....
field :email, :string, required: {__MODULE__, :require_email?}
Support validate array item with :each
option, each
accept a list of validators
...
field :values, {:array, :number}, each: [number: [min: 20, max: 50]]
...
If you find a bug or want to improve something, please send a pull request. Thank you!