tisdag, september 19, 2006

Announcing Ducktator - A Duck Type Validator

As I hinted in my last post, I feel with all my heart that there should be some way to actively validate my static expectations on certain kinds of objects. Now, respond_to? and friends are fine, but they do not scale. Not at all. So, I have built Ducktator - a duck type validator. It uses a very recursive, extensible rule syntax. Rules can be specified in either YAML or simple Ruby, with hashes and arrays and all that stuff.

First though, where would that be useful? Not everywhere of course, but these are the places that just drops into my head when writing this: 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 is very easy to extend. Basically, you just create a method on the validator whose name begins with "check_" and this will be automatically called for all objects. The base library is divided into modules that are mixed-in to the central Validator. I won't detail exact usage here, but just show an example. First, the rule file, which resides in rules.yml:

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

Then, our code to create a Validator from this:

require 'ducktator'
v = Ducktator::from_file('rules.yml')

And lastly, to use it to validate the objects foo and bar:

foo = {'baz' => 13}
bar = {'b1' => [:try1, 130],
'q16' => [:foobaz, 255]}
v.valid?(foo) # => false
v.valid?(foo,bar) # => false
v.valid?(bar) # => true


Whereto
Now, you'll certainly be wondering where to get this interesting code. As always, it will be found on RubyForge here, and the first release is available through gems, so just gem install ducktator and you should be set to go.

It is licensed with a nice MIT license and I am the project creator, maintainer et al.

3 kommentarer:

Anonym sa...

So is this kind of dynamic code introspection a la Monitor Functions & name checking ( cf. http://www.erikveen.dds.nl/monitorfunctions/index.html and http://redcorundum.blogspot.com/2006/05/kernelqualifiedconstget.html )?

Ola Bini sa...

Hi,

No, not really. Those are interesting ideas in themselves, but this is just a class library that lets you check deep hierarchies of objects for certain characteristics. For example, you could see that an object you have (which could be an argument, or something entirely other) is something that responds to each, and that each value yielded by that each includes enumerable, and that if you call the method xyz on that value it will return something that respond_to? :read.

This is slightly convoluted, since those are the situations where this makes sense. If you don't have need for complex validations of data objects, this is not it.

Markus Jais sa...

cool stuff. I will add this to my bimonthly Ruby news column I write
for the German magazine "Der Entwickler".

Markus