Argx Hex Versiondocs

DSLs for checking args.

Installation

Add argx to your list of dependencies in mix.exs:

defp deps do
  [{:argx, "~> 1.1.2"}]
end

Install via mix deps.get and the happy check your args as described in Usage and Advanced.

Example

This Example Project is the basis for Argx, help you use well. Download via Gitee or Github.

Usage

Quick Start

Here’s a commented example.

# Use Argx like this in Your Project.
iex> defmodule YourProject do
...>   # step 1: introduce check function by Argx module
...>   use Argx
...>
...>   # step 2: define rule
...>   defconfig(Rule, id(:string))
...>
...>   def get(args) do
...>     # step 3: use check function to check args
...>     check(args, [Rule])
...>   end
...> end

# Return errors.
iex> YourProject.get(%{id: 1})
{:error, ["error type: id"]}

# If passed, return original args.
iex> YourProject.get(id: "a")
[id: "a"]

Check Via DSL

# step 1: define your validator
defmodule YourProject.Validator do
  use Argx.WithCheck
end

defmodule YourProject do
  # step 2: import your validator
  import YourProject.Validator

  # step 3: use with_check macro to wrap your function(s)
  with_check configs(id(:string)) do
    def get(id) do
      {id}
    end
  end
end

Advanced

1. How to share arg configs?

step 1: create a module for define shared arg configs.

defmodule YourProject.ArgConfigs do
  use Argx.Defconfig
  defconfig(NumberRule, number(:string, :empty))
  defconfig(PageSizeRule, page_size(:integer, :auto, 1..100) || 10)
end

step 2 : config share module to the following positions.

use Argx, share: YourProject.ArgConfigs
# or
use Argx.WithCheck, share: YourProject.ArgConfigs

step 3 : use arg config by name.

def get(args) do
  check(args, [NumberRule, PageSizeRule])
  |> case do
    {:error, _} -> :error
    _ -> :ok
  end
end
# or
with_check configs(NumberRule, PageSizeRule) do
  def get(id) do
    {id}
  end
end

2. Format errors

just implement callback fmt_errors/1, Argx invoke your custom format errors function, when check done.

There are 3 places to put it.

Highest priority: in the current module.

defmodule YourProject do
  use Argx
  def fmt_errors({:error, _errors}), do: :error
  def fmt_errors(_new_args_or_result), do: :ok
  ...
end
# or
defmodule YourProject do
  import YourProject.Validator
  def fmt_errors({:error, _errors}), do: :error
  def fmt_errors(_new_args_or_result), do: :ok
  ...
end

Second priority: in the share arg configs module.

defmodule YourProject.ArgConfigs do
  use Argx.Defconfig
  def fmt_errors({:error, _errors}), do: :error
  def fmt_errors(_new_args_or_result), do: :ok
  ...
end

Lowest priority: if you use argx via with_check, also implement it in the definition module.

defmodule YourProject.Validator do
  use Argx.WithCheck
  def fmt_errors({:error, _errors}), do: :error
  def fmt_errors(_new_args_or_result), do: :ok
  ...
end

Features

Support Data Type

check/2 function

DSL

defconfig

Reuse arg configs by name.

with_check

Errors

There are 5 types.

  1. lacked some fields.
  2. some fields' type is error.
  3. some field's range/length/size is out of range.
  4. checkbox functionality error.
  5. radio functionality error.

As shown below:

{
  :error,
  [
    error_type: ["cargoes:1:number", "cargoes:2:name"], # report nested data's error
    lacked: [:mobile],
    out_of_range: [:weight],
    checkbox_error: [:id, :number],
    radio_error: [:ip, :addr]
  ]
}

If you want to convert meta errors to readable message, just implement fmt_errors/1.

Configuration

config Argx or Argx.WithCheck module.

  1. set shared arg configs module.
  2. set warn flag.
    use Argx.WithCheck, share: YourProject.ArgConfigs, warn: false

Benchee Report

Name ips average deviation median 99th % Recommand
without Argx 3090.90 K 0.32 μs ±13466.34% 0 μs 0.90 μs -
with_check DSL 55.57 K 17.99 μs ±124.26% 15.90 μs 56.90 μs YES
check 22.64 K 44.18 μs ±94.15% 36.90 μs 153.90 μs NO

Benchmark

mix bench
## ArgxBench
benchmark name                  iterations   average time 
deep match (4 nested level)     50000        44.65 µs/op

Contributing

Contributions to Argx are very welcome!

Bug reports, documentation, spelling corrections... all of those (and probably more) are much appreciated contributions!