Ducktator - the Duck Type Validator

Ducktator is a small library to enable Ruby systems to generically validate objects introspectively. In plain speak, check certain common methods of objects, and see if they match what your schema expects the values to be. This capability is not necessary for most applications, but sometimes it’s highly useful. For example, validating objects that have been serialized or marshallad. Validating what you get when loading YAML files, so that the object graph matches what your code does. Write test cases that expect a complicated object back. The possibilities are many.

Ducktator can be configured either with YAML or directly using simple Hashes. The syntax is very recursive, extensible and easy. I will use YAML for the examples in this document, but for easier validations it may be better just creating the Hash directly.

Validator usage

The main way into the Ducktator validator framework are a couple of factory methods in the Ducktator namespace. To create a new Validator from a YAML file you could do it like this: (in this case, there must be a root key inside the YAML document)

Ducktator::from_file('validations.yml') # => #<Ducktator::Validator ...>

You can also create a Validator from a String directly.

Ducktator::from('class: String') # => #<Ducktator::Validator ...>

If you just want to do a one time validation, this can be done like this:

Ducktator::valid?('class: String', 123) # => false

or like this:

Ducktator::valid?('class' => String, 'abc') # => true

Using the Validator object is mostly as simple as calling the method valid? and send it the objects you want to validate. valid? will return true only if all its arguments are valid ackording to its validation rules:

p v # => #<Ducktator::Validator ...>
v.valid?("str1")
v.valid?("str1","str2","str3")

Validators can be combined with & and |, like this:

vx = v1 & (v2 | v3) & v4

Validation specification

The validation specification will contain one or more validations to check against. A validation always has a value. It can be scalar, a sequence or a mapping. If it’s a mapping, it will be interpolated as a new specification. A simple YAML file that validates a Hash, that should have String keys and values that are Array‘s with index 0 being a Symbol and index 1 an Integer which is maximum 256: (note that the root: is necessary, unless loading the YAML directly from a String)

---
root:
 class: Hash
 each_key: {class: String}
 each_value:
   class: Array
   value:
   - - 0
     - class: Symbol
   - - 1
     - class: Integer
     - max: 256

More than one validation can exist in the same file, just use Ducktator#from_file‘s second, optional argument, which defaults to “root”.

Author

Ola Bini <[email protected]>

License

Ducktator is distributed with a MIT license, which can be found in the file LICENSE.