arianna documentation

->>

macro

[& validators]

Creates a validator that chains the result of one validator into the next. Validators that are tests, such as is will have output the same as their input. Any failed validation or sucessful is-optional test will terminate the evaluation. The validation error will contain a key :chain which contains the chain of validation results that led to the error.

->> is a macro that has a number of interpretation rules that transform normal clojure syntax into validators.

  • string? becomes (v/is string?)
  • inc becomes (v/as inc)
  • :key becomes (v/as-key :key)
  • ["City" "Zip"] becomes (v/as-key ["City" "Zip"])

is is used if the name of the function ends with a question mark or if it's a comparison operator in clojure.core.

Chaining these together gives you the ability to do things like this:

(v/->> :should-be-even v/required v/number even?)
;;; Input should be a map with a key :should-be-even
;;; that can be read as a number and that number is even.

(v/->> :email v/optional v/email?)
;;; Input should be an email address or blank.

(v/->> keys (v/are keyword?))
;;; Input should be a map where all the keys are keywords

Next, if you follow a validator with a map, it will be merged into the validator.

(v/->> :email {:not-found "xjobcon@phx.cam.ac.uk"})
;;; Provides a default email address
;;; see also `as-key` for more details

Finally, strings are treated as maps with a :arianna/message key. These are used to provide human readable feedback by using stencil/mustache on the validation errors.

(v/->> :email
       v/required "You must provide an email."
       v/email? "The input {{value}} doesn't appear to be an email address.")

absent?

fn

[rules value]

Method that is used to determine if the value is absent in some way. Rules should be a set. The possible values of the set are:

  • :nil - return true if the value is nil
  • :blank - return true if the value is an empty string
  • :missing - return true if the value is :arianna/missing

The last, :missing checks for the special value :arianna/missing returned by as-key when it fails to find the key.

always-true

var

A validator that returns true for any input. Only really useful at the repl.

and

macro

[& validators]

Takes a sequence of validators and creates a validator that applies them all, terminating if one fails.

and has similar interpretation rules to ->>:

  • string? becomes (v/is string?)
  • inc becomes (v/is inc)
  • :key becomes (v/has :key)
  • ["City" "Zip"] becomes (v/as-key ["City" "Zip"])

Note the differences:

  • inc is treated as a test (since a transform would make no sense)
  • if :key cannot be found, it's treated as a validation failure.

and-all

macro

[& validators]

Takes a sequence of validators and creates a validator that applies them all, failing but not terminating if one fails. It will return all validation errors, while and will only return the first.

Uses the same interpretation rules as and.

are

macro

[predicate & args]

Returns a validator which will call (predicate ~@args x) on every element x in the input value. Can use clojure's % syntax like an anonymous function, so (v/are < % 10) will call (< input 10) on each element.

predicate must be a symbol.

as

macro

[projection & args]

Returns a validator which will call (projection ~@args input). This will fail if the returned value is equal to :arianna/fail. By default, this means it will fail if the returned value is nil.

(v/as number)
;;; will fail if the input was not a number or a string
;;; representing a number

(assoc (v/as inc) :arianna/fail 3)
;;; Will fail if the input was equal to 2

Supports use of the % symbol, same as is.

as-key

fn

[projection]

Returns a validator which will look into a map. Takes a keyword or a vector. as-key never fails and if the map doesn't have the key specified the result will be the special value :arianna/missing. You can test for this with v/required, v/optional or (v/is v/absent? #{:missing}). (The first two also test for nil and blank strings.)

Expands to one of

(as get-in % v :arianna/missing)
(as get % v :arianna/missing)

And sets :arianna/fail to :arianna/never.

The :not-found key is the value returned if the value is missing.

(v/as-key :x)
;;; Returns :arianna/missing if :x is not present
(assoc (v/as-key :x) :not-found 3)
;;; Returns 3 if :x is not present
(v/->> :x {:not-found 3})
;;; Exactly the same as the last example

Note that get will be used if as-key is given a vector with one element. (This makes reporting the results simpler later, since get-in [:x] is functionally identical to get :x.)

assert-valid

macro

[expr & validators]

Tests the value of expr with validators. If it passes, returns the value. If not, throws an exception with validation, line and file information attached.

Applies and-all to validators.

Note that this takes the expr first, making it suitable for use with ->, and can be used to validate that long chains of -> have usable intermediate values.

(-> x
    inc
    (* 4)
    (v/assert-valid even?)
    (/ 2))

comp

macro

[& validators]

Functionally identical to ->> except that it evaluates the validators right to left instead of left to right.

cond

macro

[& clauses]

Creates a validator function that checks multiple conditions. Each clause is a pair of a predicate and a validator. Like cond, you can put :else as the last predicate. If you fail a clause, you get back that clause's validator as a failure. If no clauses match you get back the cond validator.

Uses the same rules as and on the predicate clauses, and the same rules as ->> on the validator clauses. That said, adding a message to the predicate is pretty pointless.

contains-in?

fn

[coll key]

The equivalent of contains? for vectors. The counterpart of get-in and get. Normally you won't want to call it directly, but v/has uses it.

email?

fn

[v]

Returns true if v is an email address.

every

macro

[& validators]

Returns a validator that applies the validators to each element of the input collection.

Uses the same interpretation rules as and.

field

fn

[validation-error]

Identifies the field associated with a validation error. One of the following:

  • The :arianna/field of the validator, if any.
  • The projection of v/as-key.

If the :arianna/field property isn't available, it will scan back through the validation chain for:arianna/field. If that fails, it will scan forward through the chain for a projection. Only then will it check the current validator for a projection.

has

fn

[projection]

has behaves the same as as-key, expect that if the projection does not have a value, the validator fails.

Expands to one of

(is m/contains-in? % v)
(is contains? % v)

in-range?

fn

[min-incl max-excl value]

Method that checks if its value is numeric and is between min, inclusive, and max, exclusive.

is

macro

[predicate & args]

Returns a validator which will call (predicate ~@args input). Can use clojure's % syntax like an anonymous function, so (v/is < % 10) will call (< input 10).

predicate must be a symbol.

Example usages

(v/is string?)
(v/is < % 10)

is-not

macro

[predicate & args]

Returns a validator, like is, which will call (not (predicate ~@args input)). Supports % the same way as is.

predicate must be a symbol.

is-optional

macro

[predicate & args]

Returns a validator, like is, which will call (predicate ~@args input). The validation result is always true, but if the test is true the composite predicate will immediately short-circuit. Supports % the same way as is.

Example usage:

(v/is-optional v/absent? #{:nil :blank})

Which prevents evaluation of subsequent validators if the value is nil or blank.

Although callable anywhere, it only really makes sense to use it within v/->>.

predicate must be a symbol.

number

fn

[s]

Transform method that tries to convert s to a number. Returns nil on failure.

optional

var

Shorthand for (v/is-optional absent? #{:missing :nil :blank}).

Example usage:

(v/->> :email v/optional v/email?)

A rule that says that either :email is a valid email or it's not present.

or

macro

[& validators]

Takes a sequence of validators and creates a validator that applies them all, terminating if one succeeds. If it does not succeed, it will have a validation error that keys the or validator and an :errors key that contains a list of all of the constituent errors.

Uses the same interpretation rules as and.

parse-decimal-number

fn

[s]

Reads a number from a string. Returns nil if not a number.

regex-match?

fn

[regex v]

Returns true if the string v matches the given regular expression.

render-message

fn

[validation-error]

Generates a human readable message from a validation error specified by the failing validator.

The message rule is specified by the :arianna/message key in the validator. It can be either a function that takes a validation error or an implementation of the ValidationMessage protocol. Importantly, strings implement the protocol and work as mustache templates.

Stuck together with the interpretation rules of composites, the easiest way to set a message is by putting a string after the validation expression.

(v/and number?  "Input should be a number."
       even?    "{{value}} should have been even."
       (< % 10) "{{value}} should have been less than {{validator.y}}.")

Usually, you won't call this method directly, but just get the results from v/summarize.

required

var

Shorthand for (v/is-not absent? #{:missing :nil :blank}).

Example usage:

(v/->> :email v/required v/email?)

A rule that says that :email is both present and a valid email.

summarize

fn

[vr]
[validator input]

Arity 1: Turns a validation result into a map of field, list of message. Returns nil on success.

Arity 2: Summarizes the result of validating the input.

Check the documentation for render-message and field for how this gets generated.

valid?

fn

[{:keys [status]}]
[value validator]

Arity 1: Returns true if the validation result is a pass.

Arity 2: Returns true if value passes the validator.

validate

fn

[validator value]

Validates a value against a validator. Exceptions thrown during validation will be reported as validation failures with the exception in an :exception key of the validation error.

validate-debug

fn

[validator value]

Validates a value against a validator. Will not catch exceptions the way that validate does. Intended to assist with tracking down errors.

when

macro

[& validators]

Returns a validator that only checks the following validators when the first validates. Interpets all validators using the same rules as and.

within?

fn

[min-incl max-incl value]

Method that checks if its value is between min-incl and max-incl, both inclusive. Uses clojure.core/compare to compare values.