File Coverage

blib/lib/Validator/Custom/Rule.pm
Criterion Covered Total %
statement 95 100 95.0
branch 11 14 78.5
condition 8 11 72.7
subroutine 13 14 92.8
pod 11 12 91.6
total 138 151 91.3


line stmt bran cond sub pod time code
1             # Version 0 module
2             package Validator::Custom::Rule;
3 5     5   24531 use Object::Simple -base;
  5         1310  
  5         35  
4 5     5   442 use Carp 'croak';
  5         12  
  5         6342  
5              
6             has 'topic_info' => sub { {} };
7             has 'rule' => sub { [] };
8             has 'validator';
9              
10             sub default {
11 1     1 1 2 my ($self, $default) = @_;
12            
13 1         22 $self->topic_info->{default} = $default;
14            
15 1         7 return $self;
16             }
17              
18             sub name {
19 0     0 1 0 my ($self, $name) = @_;
20            
21 0         0 $self->topic_info->{name} = $name;
22            
23 0         0 return $self;
24             }
25              
26             sub filter {
27 10     10 1 12 my $self = shift;
28            
29 10         24 return $self->check(@_)
30             }
31              
32             sub check {
33 41     41 1 56 my $self = shift;
34            
35 41         76 my @constraints = @_;
36              
37 41         63 my $constraints_h = [];
38 41         75 for my $constraint (@constraints) {
39 41         69 my $constraint_h = {};
40 41 100       88 if (ref $constraint eq 'ARRAY') {
41 6         14 $constraint_h->{constraint} = $constraint->[0];
42 6         12 $constraint_h->{message} = $constraint->[1];
43             }
44             else {
45 35         82 $constraint_h->{constraint} = $constraint;
46             }
47 41         836 my $cinfo = $self->validator->_parse_constraint($constraint_h);
48 41         923 $cinfo->{each} = $self->topic_info->{each};
49 41         310 push @$constraints_h, $cinfo;
50             }
51              
52 41   100     858 $self->topic_info->{constraints} ||= [];
53 41         314 $self->topic_info->{constraints} = [@{$self->topic_info->{constraints}}, @{$constraints_h}];
  41         856  
  41         1082  
54            
55 41         339 return $self;
56             }
57              
58             sub message {
59 11     11 1 17 my ($self, $message) = @_;
60            
61 11   50     213 my $constraints = $self->topic_info->{constraints} || [];
62 11         78 for my $constraint (@$constraints) {
63 23   66     127 $constraint->{message} ||= $message;
64             }
65            
66 11         27 return $self;
67             }
68              
69             sub topic {
70 36     36 0 48 my ($self, $key) = @_;
71            
72             # Create topic
73 36         52 my $topic_info = {};
74 36         77 $topic_info->{key} = $key;
75 36         826 $self->topic_info($topic_info);
76              
77             # Add topic to rule
78 36         182 push @{$self->rule}, $self->topic_info;
  36         778  
79            
80 36         684 return $self;
81             }
82              
83             sub each {
84 5     5 1 8 my $self = shift;
85            
86 5 50       12 if (@_) {
87 5         107 $self->topic_info->{each} = $_[0];
88 5         36 return $self;
89             }
90             else {
91 0         0 return $self->topic_info->{each};
92             }
93            
94 0         0 return $self;
95             }
96              
97             sub optional {
98 1     1 1 4 my ($self, $key) = @_;
99            
100 1 50       5 if (defined $key) {
101             # Create topic
102 1         2 $self->topic($key);
103             }
104            
105             # Value is optional
106 1         28 $self->rule->[-1]{option}{optional} = 1;
107            
108 1         9 return $self;
109             }
110              
111             sub require {
112 35     35 1 212 my ($self, $key) = @_;
113              
114             # Create topic
115 35 50       85 if (defined $key) {
116 35         78 $self->topic($key);
117             }
118            
119 35         131 return $self;
120             }
121              
122             sub parse {
123 159     159 1 270 my ($self, $rule, $shared_rule) = @_;
124            
125 159   100     332 $shared_rule ||= [];
126            
127 159         245 my $normalized_rule = [];
128            
129 159         257 for (my $i = 0; $i < @{$rule}; $i += 2) {
  530         1435  
130            
131 373         503 my $r = {};
132            
133             # Key, options, and constraints
134 373         607 my $key = $rule->[$i];
135 373         579 my $option = $rule->[$i + 1];
136 373         436 my $constraints;
137 373 100       791 if (ref $option eq 'HASH') {
138 22         70 $constraints = $rule->[$i + 2];
139 22         27 $i++;
140             }
141             else {
142 351         466 $constraints = $option;
143 351         542 $option = {};
144             }
145 373         538 my $constraints_h = [];
146            
147 373 100       800 if (ref $constraints eq 'ARRAY') {
148 371         688 for my $constraint (@$constraints, @$shared_rule) {
149 405         535 my $constraint_h = {};
150 405 100       785 if (ref $constraint eq 'ARRAY') {
151 86         211 $constraint_h->{constraint} = $constraint->[0];
152 86         155 $constraint_h->{message} = $constraint->[1];
153             }
154             else {
155 319         762 $constraint_h->{constraint} = $constraint;
156             }
157 405         9212 push @$constraints_h, $self->validator->_parse_constraint($constraint_h);
158             }
159             } else {
160 2         10 $constraints_h = {
161             'ERROR' => {
162             value => $constraints,
163             message => 'Constraints must be array reference'
164             }
165             };
166             }
167            
168 371         747 $r->{key} = $key;
169 371         592 $r->{constraints} = $constraints_h;
170 371         576 $r->{option} = $option;
171            
172 371         839 push @$normalized_rule, $r;
173             }
174            
175 157         3596 $self->rule($normalized_rule);
176            
177 157         1014 return $self;
178             }
179              
180             sub copy {
181 1     1 1 3 my ($self, $copy) = @_;
182              
183 1         22 $self->topic_info->{option}{copy} = $copy;
184            
185 1         9 return $self;
186             }
187              
188             sub check_or {
189 6     6 1 15 my ($self, @constraints) = @_;
190              
191 6         8 my $constraint_h = {};
192 6         15 $constraint_h->{constraint} = \@constraints;
193            
194 6         128 my $cinfo = $self->validator->_parse_constraint($constraint_h);
195 6         129 $cinfo->{each} = $self->topic_info->{each};
196            
197 6   50     152 $self->topic_info->{constraints} ||= [];
198 6         58 push @{$self->topic_info->{constraints}}, $cinfo;
  6         122  
199            
200 6         46 return $self;
201             }
202              
203             1;
204              
205             =head1 NAME
206              
207             Validator::Custom::Rule - Rule object
208              
209             =head1 SYNOPSYS
210            
211             use Validator::Custom;
212             my $vc = Validator::Custom->new;
213            
214             # Create rule object
215             my $rule = $vc->create_rule;
216             $rule->require('id')->check(
217             'ascii'
218             );
219             $rule->optional('name')->check(
220             'not_blank'
221             );
222            
223             # Validate
224             my $data = {id => '001', name => 'kimoto'};
225             my $result = $vc->validate($data, $rule);
226            
227             # Option
228             $rule->require('id')->default(4)->copy(0)->message('Error')->check(
229             'not_blank'
230             );
231              
232             =head1 DESCRIPTION
233              
234             Validator::Custom::Rule is the class to parse rule and store it as object.
235              
236             =head1 ATTRIBUTES
237              
238             =head2 rule
239              
240             my $content = $rule_obj->rule;
241             $rule_obj = $rule->rule($content);
242              
243             Content of rule object.
244              
245             =head1 METHODS
246              
247             =head2 each
248              
249             $rule->each(1);
250              
251             Tell checke each element.
252              
253             =head2 check
254              
255             $rule->check('not_blank')->check('ascii');
256              
257             Add constraints to current topic.
258              
259             =head2 check_or
260              
261             $rule->check_or('not_blank', 'ascii');
262              
263             Add "or" condition constraints to current topic.
264              
265             =head2 copy
266              
267             $rule->copy(0);
268              
269             Set copy option
270              
271             =head2 default
272              
273             $rule->default(0);
274              
275             Set default option
276              
277             =head2 filter
278              
279             $rule->filter('trim');
280              
281             This is C method alias for readability.
282              
283             =head2 message
284              
285             $rule->require('name')
286             ->check('not_blank')->message('should be not blank')
287             ->check('int')->message('should be int');
288              
289             Set message for each check.
290              
291             Message is fallback to before check
292             so you can write the following way.
293              
294             $rule->require('name')
295             ->check('not_blank')
296             ->check('int')->message('should be not blank and int');
297              
298             =head2 name
299              
300             $rule->name('key1');
301              
302             Set result key name
303              
304             =head2 optional
305              
306             $rule->optional('id');
307              
308             Set key and set require option to 0.
309              
310             =head2 require
311              
312             $rule->require('id');
313             $rule->require(['id1', 'id2']);
314              
315             Set key.
316              
317             =head2 parse
318              
319             $rule_obj = $rule_obj->parse($rule);
320              
321             Parse rule and store it to C attribute.