1Declare::Constraints::SUismeprleC(o3n)tributed Perl DocuDmeecnltaartei:o:nConstraints::Simple(3)
2
3
4

NAME

6       Declare::Constraints::Simple - Declarative Validation of Data
7       Structures
8

SYNOPSIS

10         use Declare::Constraints::Simple-All;
11
12         my $profile = IsHashRef(
13                           -keys   => HasLength,
14                           -values => IsArrayRef( IsObject ));
15
16         my $result1 = $profile->(undef);
17         print $result1->message, "\n";    # 'Not a HashRef'
18
19         my $result2 = $profile->({foo => [23]});
20
21         print $result2->message, "\n";    # 'Not an Object'
22
23         print $result2->path, "\n";
24                           # 'IsHashRef[val foo].IsArrayRef[0].IsObject'
25

DESCRIPTION

27       The main purpose of this module is to provide an easy way to build a
28       profile to validate a data structure. It does this by giving you a set
29       of declarative keywords in the importing namespace.
30

USAGE

32       This is just a brief intro. For details read the documents mentioned in
33       "SEE ALSO".
34
35   Constraint Import
36         use Declare::Constraints::Simple-All;
37
38       The above command imports all constraint generators in the library into
39       the current namespace. If you want only a selection, use "only":
40
41         use Declare::Constraints::Simple
42             Only => qw(IsInt Matches And);
43
44       You can find all constraints (and constraint-like generators, like
45       operators. In fact, "And" above is an operator. They're both
46       implemented equally, so the distinction is a merely philosophical one)
47       documented in the Declare::Constraints::Simple::Library pod. In that
48       document you will also find the exact parameters for their usage, so
49       this here is just a brief Intro and not a coverage of all
50       possibilities.
51
52   Building a Profile
53       You can use these constraints by building a tree that describes what
54       data structure you expect. Every constraint can be used as sub-
55       constraint, as parent, if it accepts other constraints, or stand-alone.
56       If you'd just say
57
58         my $check = IsInt;
59         print "yes!\n" if $check->(23);
60
61       it will work too. This also allows predefining tree segments, and
62       nesting them:
63
64         my $id_to_objects = IsArrayRef(IsObject);
65
66       Here $id_to_objects would give it's OK on an array reference containing
67       a list of objects. But what if we now decide that we actually want a
68       hashref containing two lists of objects? Behold:
69
70         my $object_lists =
71           IsHashRef( HasAllKeys( qw(good bad) ),
72                      OnHashKeys( good => $id_to_objects,
73                                  bad  => $id_to_objects ));
74
75       As you can see, constraints like "IsArrayRef" and "IsHashRef" allow you
76       to apply constraints to their keys and values. With this, you can step
77       down in the data structure.
78
79   Applying a Profile to a Data Structure
80       Constraints return just code references that can be applied to one
81       value (and only one value) like this:
82
83         my $result = $object_lists->($value);
84
85       After this call $result contains a Declare::Constraints::Simple::Result
86       object. The first think one wants to know is if the validation
87       succeeded:
88
89         if ($result->is_valid) { ... }
90
91       This is pretty straight forward. To shorten things the result object
92       also overloads it's "bool"ean context. This means you can alternatively
93       just say
94
95         if ($result) { ... }
96
97       However, if the result indicates a invalid data structure, we have a
98       few options to find out what went wrong. There's a human parsable
99       message in the "message" accessor. You can override these by forcing it
100       to a message in a subtree with the "Message" declaration. The "stack"
101       contains the name of the chain of constraints up to the point of
102       failure.
103
104       You can use the "path" accessor for a joined string path representing
105       the stack.
106
107   Creating your own Libraries
108       You can declare a package as a library with
109
110         use Declare::Constraints::Simple-Library;
111
112       which will install the base class and helper methods to define
113       constraints. For a complete list read the documentation in
114       Declare::Constraints::Simple::Library::Base. You can use other
115       libraries as base classes to include their constraints in your export
116       possibilities. This means that with a package setup like
117
118         package MyLibrary;
119         use warnings;
120         use strict;
121
122         use Declare::Constraints::Simple-Library;
123         use base 'Declare::Constraints::Simple::Library';
124
125         constraint 'MyConstraint',
126           sub { return _result(($_[0] >= 12), 'Value too small') };
127
128         1;
129
130       you can do
131
132         use MyLibrary-All;
133
134       and have all constraints, from the default library and yours from
135       above, installed into your requesting namespace. You can override a
136       constraint just by redeclaring it in a subclass.
137
138   Scoping
139       Sometimes you want to validate parts of a data structure depending on
140       another part of it. As of version 2.0 you can declare scopes and store
141       results in them. Here is a complete example:
142
143         my $constraint =
144           Scope('foo',
145             And(
146               HasAllKeys( qw(cmd data) ),
147               OnHashKeys(
148                 cmd => Or( SetResult('foo', 'cmd_a',
149                              IsEq('FOO_A')),
150                            SetResult('foo', 'cmd_b',
151                              IsEq('FOO_B')) ),
152                 data => Or( And( IsValid('foo', 'cmd_a'),
153                                  IsArrayRef( IsInt )),
154                             And( IsValid('foo', 'cmd_b'),
155                                  IsRegex )) )));
156
157       This profile would accept a hash references with the keys "cmd" and
158       "data". If "cmd" is set to "FOO_A", then "data" has to be an array ref
159       of integers. But if "cmd" is set to "FOO_B", a regular expression is
160       expected.
161

SEE ALSO

163       Declare::Constraints::Simple::Library,
164       Declare::Constraints::Simple::Result,
165       Declare::Constraints::Simple::Base, Module::Install
166

REQUIRES

168       Carp::Clan, aliased, Class::Inspector, Scalar::Util, overload and
169       Test::More (for build).
170

TODO

172       •   Examples.
173
174       •   A list of questions that might come up, together with their
175           answers.
176
177       •   A "Custom" constraint that takes a code reference.
178
179       •   Create stack objects that stringify to the current form, but can
180           hold more data.
181
182       •   Give the "Message" constraint the ability to get the generated
183           constraint inserted in the message. A possibility would be to
184           replace __Value__ and __Message__. It might also accept code
185           references, which return strings.
186
187       •   Allow the "IsCodeRef" constraint to accept further constraints. One
188           might like to check, for example, the refaddr of a closure.
189
190       •   A "Captures" constraint that takes a regex and can apply other
191           constraints to the matches.
192
193       •   ???
194
195       •   Profit.
196

INSTALLATION

198         perl Makefile.PL
199         make
200         make test
201         make install
202
203       For details read Module::Install.
204

AUTHOR

206       Robert 'phaylon' Sedlacek "<phaylon@dunkelheit.at>"
207
209       This module is free software, you can redistribute it and/or modify it
210       under the same terms as perl itself.
211
212
213
214perl v5.36.0                      2023-01-20   Declare::Constraints::Simple(3)
Impressum