Exvalibur
generator for blazingly fast validators of maps based on sets of predefined rules
Installation
Simply add exvalibur to your list of dependencies in mix.exs:
def deps do
[
{:exvalibur, "~> 0.1"}
]
endUsage
rules = [
%{matches: %{currency_pair: "EURUSD"},
conditions: %{rate: %{min: 1.0, max: 2.0}}}]
Exvalibur.validator!(rules, module_name: Exvalibur.Validator)
Exvalibur.Validator.valid?(%{currency_pair: "EURUSD", rate: 1.5})
#⇒ {:ok, %{currency_pair: "EURUSD", rate: 1.5}}
Exvalibur.Validator.valid?(%{currency_pair: "EURGBP", rate: 1.5})
#⇒ :error
Exvalibur.Validator.valid?(%{currency_pair: "EURUSD", rate: 0.5})
#⇒ :error
rules = [
%{matches: %{currency_pair: "EURGBP"},
conditions: %{rate: %{min: 1.0, max: 2.0}}}]
Exvalibur.validator!(rules, module_name: Exvalibur.Validator)
Exvalibur.Validator.valid?(%{currency_pair: "EURGBP", rate: 1.5})
#⇒ {:ok, %{currency_pair: "EURGBP", rate: 1.5}}
Exvalibur.Validator.valid?(%{currency_pair: "EURUSD", rate: 1.5})
#⇒ {:ok, %{currency_pair: "EURUSD", rate: 1.5}}Sigils To Pattern Match Data
Starting with v0.4.0 we support ~q and ~Q sigils to use validator with
pattern matching.
import Exvalibur.Sigils
starting_with = "bar"
rules = [%{matches: %{foo: ~q[<<"#{starting_with}", _::binary>>]}}]
Exvalibur.validator!(rules, module_name: TestValidator)
assert TestValidator.valid?(%{foo: "bar"}) == {:ok, %{foo: "bar"}}
assert TestValidator.valid?(%{foo: "zzz"}) == :error
assert TestValidator.valid?(%{foo: 42}) == :errorBinary Conditions
Starting with v0.5.0 we support binary conditions for the declared guards.
import Exvalibur.Sigils
rules = [%{conditions: "num >= 0 and num <= 100"}]
Exvalibur.validator!(rules, module_name: TestValidator)
assert TestValidator.valid?(%{num: "bar"}) == :error
assert TestValidator.valid?(%{num: 200}) == :error
assert TestValidator.valid?(%{num: 42}) == {:ok, %{num: 42}}Any match expression allowed in function head matching clause is allowed here.
import Exvalibur.Sigils
rules = [%{matches: %{foo: ~Q[%{} = _]}}]
Exvalibur.validator!(rules, module_name: TestValidator)
assert TestValidator.valid?(%{foo: %{bar: "baz"}}) == {:ok, %{foo: %{bar: "baz"}}}
assert TestValidator.valid?(%{foo: 42}) == :errorCustom Guards
Starting with v0.6.0 we support arbitrary custom guards in rules. The variables
used in these guards should be explicitly declared under the matches key in rules,
in the form foo: ~Q[foo].
import Exvalibur.Sigils
rules = [%{
matches: %{num: ~Q[num]},
guards: ["num >= 0 and num <= 100"]
}]
Exvalibur.validator!(rules, module_name: TestValidator)
assert TestValidator.valid?(%{num: "bar"}) == :error
assert TestValidator.valid?(%{num: 200}) == :error
assert TestValidator.valid?(%{num: 42}) == {:ok, %{num: 42}}Module-based validators
defmodule Validator do
use Exvalibur, rules: [
%{
matches: %{currency_pair: <<"EUR", _ :: binary>>},
conditions: %{foo: %{min: 0, max: 100}},
guards: %{num: num > 0 and num < 100}}]
end
Validator.valid?(%{currency_pair: "EURUSD", foo: 50, num: 50})
#⇒ {:ok, %{currency_pair: "EURUSD", foo: 50, num: 50}}
Validator.valid?(%{currency_pair: "USDEUR", foo: 50, num: 50})
#⇒ :error
Validator.valid?(%{currency_pair: "EURUSD", foo: -50, num: 50})
#⇒ :error
Validator.valid?(%{currency_pair: "EURUSD", foo: 50, num: -50})
#⇒ :errorChangelog
0.10.0
@behaviour Exvalibur.Validatablewith overridablecustom_validate/1
0.9.0
valid?/1is deprecated in favor ofvalidate/1; starting withv1.0valid?/1will returnbooleanvalue
0.8.0
- module-based validators