NAME
Declare::Constraints::Simple - Declarative Validation of Data Structures
SYNOPSIS
use Declare::Constraints::Simple-All;
my $profile = IsHashRef(
-keys => HasLength,
-values => IsArrayRef( IsObject ));
my $result1 = $profile->(undef);
print $result1->message, "\n"; # 'Not a HashRef'
my $result2 = $profile->({foo => [23]});
print $result2->message, "\n"; # 'Not an Object'
print $result2->path, "\n";
# 'IsHashRef[val foo].IsArrayRef[0].IsObject'
DESCRIPTION
The main purpose of this module is to provide an easy way to build a profile to validate a data structure. It does this by providing you with a set of declarative keywords exported into your namespace.
USAGE
use Declare::Constraints::Simple-All;
The above command imports all constraint generators in the library into the current namespace. If you want only a selection, use only
:
use Declare::Constraints::Simple Only => qw(IsInt Matches And);
You can find all constraints (and constraint-like generators, like operators. In fact, And
above is an operator. They're both implemented equally, so the distinction is a merely philosophical one) documented in the Declare::Constraints::Simple::Library pod. In that document you will also find the exact parameters for their usage, so this here is just a brief Intro and not a coverage of all possibilities.
You can use these constraints by building a tree that describes what data structure you expect. Every constraint can be used as sub-constraint, as parent, if it accepts other constraints, or stand-alone. If you'd just say
my $check = IsInt;
print "yes!\n" if $check->(23);
it will work too. This also allows predefining tree segments, and nesting them:
my $id_to_objects = IsArrayRef(IsObject);
Here $id_to_objects
would give it's OK on an array reference containing a list of objects. But what if we now decide that we actually want a hashref containing two lists of objects? Behold:
my $object_lists = IsHashRef( HasAllKeys( qw(good bad) ),
OnHashKeys( good => $id_to_objects,
bad => $id_to_objects ));
As you can see, constraints like IsArrayRef
and IsHashRef
allow you to apply constraints to their keys and values. With this, you can step down in the data structure.
Constraints return just code references that can be applied to one value (and only one value) like this:
my $result = $object_lists->($value);
After this call $result
contains a Declare::Constraints::Simple::Result object. The first think one wants to know is if the validation succeeded:
if ($result->is_valid) { ... }
This is pretty straight forward. To shorten things the result object also overloads it's bool
ean context. This means you can alternatively just say
if ($result) { ... }
However, if the result indicates a invalid data structure, we have a few options to find out what went wrong. There's a human parsable message in the message
accessor. You can override these by forcing it to a message in a subtree with the Message
declaration. The stack
contains the name of the chain of constraints up to the point of failure.
METHODS
import($flag, @args)
Exports the constraints to the calling namespace.
_build_handle_map()
Internal method to build constraint-to-class mappings.
_export_all($target, $handle_map)
Internal method. Exports all handles in $handle_map
into the $target
namespace.
_export_these($target, $handle_map, @constraints)
Internal method. Exports all @constraints
from $handle_map
into the $target
namespace.
SEE ALSO
Declare::Constraints::Simple::Library, Declare::Constraints::Simple::Result
REQUIRES
Carp::Clan, aliased, Class::Inspector, Scalar::Util, overload and Test::More (for build).
TODO
More tests of course!
An
OnArrayElements
constraint. LikeOnHashKeys
but for array references.Examples.
A list of questions that might come up, together with their answers.
Inheritance. Developers should be able to make their own libraries and define own constraints.
Dependencies. We need keywords like
As($name, $constraint
andIfValid($name, $constraint)
.Scoping. It would be nice to have a
Let
constraint that introduces variables. These could be set under their scope with aSetValue
constraint and retrieved withGetValue
. This would open the possibility of comparison operators.???
Profit.
AUTHOR
Robert 'phaylon' Sedlacek <phaylon@dunkelheit.at>
LICENSE AND COPYRIGHT
This module is free software, you can redistribute it and/or modify it under the same terms as perl itself.