File Coverage

blib/lib/MooX/Role/Validatable.pm
Criterion Covered Total %
statement 26 69 37.6
branch 0 18 0.0
condition n/a
subroutine 9 20 45.0
pod 8 10 80.0
total 43 117 36.7


line stmt bran cond sub pod time code
1             package MooX::Role::Validatable;
2              
3 1     1   8409 use strict;
  1         2  
  1         32  
4 1     1   17 use 5.008_005;
  1         2  
  1         37  
5             our $VERSION = '0.04';
6              
7 1     1   9 use Moo::Role;
  1         1  
  1         5  
8 1     1   595 use MooX::Role::Validatable::Error;
  1         2  
  1         36  
9 1     1   7 use Types::Standard qw( Str Int Bool ArrayRef );
  1         1  
  1         9  
10              
11 1     1   644 use Carp qw(confess);
  1         2  
  1         57  
12 1     1   4 use Scalar::Util qw/blessed/;
  1         1  
  1         895  
13              
14             has '_init_errors' => (
15             is => 'ro',
16             isa => ArrayRef,
17             init_arg => undef,
18             default => sub { return [] },
19             );
20             has '_validation_errors' => (
21             is => 'ro',
22             isa => ArrayRef,
23             init_arg => undef,
24             default => sub { return [] },
25             );
26              
27             has 'error_class' => (is => 'ro', default => sub { 'MooX::Role::Validatable::Error' }, trigger => sub {
28             my $self = shift; my $error_class = $self->error_class;
29             eval "require $error_class;";
30             confess $@ if $@;
31             } );
32              
33             has validation_methods => (
34             is => 'lazy',
35             isa => ArrayRef[Str]
36             );
37              
38             sub _build_validation_methods {
39 1     1   512 my $self = shift;
40 1         7 return [grep { $_ =~ /^_validate_/ } ($self->meta->get_all_method_names)];
  0            
41             }
42              
43             sub all_errors {
44 0     0 1   my $self = shift;
45 0           return (@{$self->{_init_errors}}, @{$self->{_validation_errors}});
  0            
  0            
46             }
47              
48             sub all_init_errors {
49 0     0 1   return @{(shift)->{_init_errors}};
  0            
50             }
51              
52             sub all_validation_errors {
53 0     0 1   return @{(shift)->{_validation_errors}};
  0            
54             }
55              
56             sub passes_validation {
57 0     0 0   my $self = shift;
58 0           my @all_errors = $self->all_errors;
59 0 0         return (scalar @all_errors) ? 0 : 1;
60             }
61              
62             sub should_alert {
63 0     0 0   my $self = shift;
64 0 0         return (grep { $_->alert } ($self->all_errors)) ? 1 : 0;
  0            
65             }
66              
67             sub confirm_validity {
68 0     0 1   my $self = shift;
69 0           $self->{_validation_errors} = [
70 0           map { $self->_errfilter($_) }
71 0           map { $self->$_ } @{$self->validation_methods}
  0            
72             ];
73 0           return $self->passes_validation;
74             }
75              
76             sub add_errors {
77 0     0 1   my ($self, @errors) = @_;
78 0           push @{ $self->{_init_errors} }, map { $self->_errfilter($_) } @errors;
  0            
  0            
79 0           return scalar @errors;
80             }
81              
82             sub initialized_correctly {
83 0     0 1   my $self = shift;
84 0 0         return (@{$self->{_init_errors}}) ? 0 : 1;
  0            
85             }
86              
87             sub all_errors_by_severity {
88 0     0 1   my $self = shift;
89 0           return (sort { $b->severity <=> $a->severity } ($self->all_errors));
  0            
90             }
91              
92             sub primary_validation_error {
93 0     0 1   my $self = shift;
94              
95 0           my @errors = $self->all_errors_by_severity;
96 0 0         return unless @errors;
97              
98             # We may wish to do something with perm v. transient here at some point.
99 0           return $errors[0];
100             }
101              
102             sub _errfilter {
103 0     0     my ($self, $error) = @_;
104 0 0         return $error if blessed($error);
105              
106 0 0         $error = { message => $error } unless ref($error); # when it's a string
107              
108 0 0         confess "Cannot add validation error which is not blessed nor hashref" unless ref($error) eq 'HASH';
109 0 0         $error->{message_to_client} = $error->{message} unless exists $error->{message_to_client};
110 0 0         $error->{set_by} = caller(1) unless exists $error->{set_by};
111 0           return $self->error_class->new($error);
112             }
113              
114 1     1   6 no Moo::Role;
  1         1  
  1         8  
115              
116             1;
117             __END__
118              
119             =encoding utf-8
120              
121             =head1 NAME
122              
123             MooX::Role::Validatable - Role to add validation to a class (Deprecated)
124              
125             =head1 SYNOPSIS
126              
127             package MyClass;
128              
129             use Moo;
130             with 'MooX::Role::Validatable';
131              
132             has 'attr1' => (is => 'lazy');
133              
134             sub _build_attr1 {
135             my $self = shift;
136              
137             # Note initialization errors
138             $self->add_errors( {
139             message => 'Error: blabla',
140             message_to_client => 'Something is wrong!'
141             } ) if 'blabla';
142             }
143              
144             sub _validate_some_other_errors { # _validate_*
145             my $self = shift;
146              
147             my @errors;
148             push @errors, {
149             message => '...',
150             message_to_client => '...',
151             };
152              
153             return @errors;
154             }
155              
156             ## use
157             my $ex = MyClass->new();
158              
159             if (not $ex->initialized_correctly) {
160             my @errors = $ex->all_init_errors();
161             ...; # We didn't even start with good data.
162             }
163              
164             if (not $ex->confirm_validity) { # does not pass those _validate_*
165             my @errors = $ex->all_errors();
166             ...;
167             }
168              
169             =head1 DESCRIPTION
170              
171             B<deprecated>. use L<MooseX::Role::Validatable>
172              
173             MooX::Role::Validatable is a Moo/Moose role which provides a standard way to add validation to a class.
174              
175             =head1 METHODS
176              
177             =head2 initialized_correctly
178              
179             no error when init the object (no add_errors is called)
180              
181             =head2 add_errors
182              
183             $self->add_errors(...)
184              
185             add errors on those lazy attributes or sub BUILD
186              
187             =head2 confirm_validity
188              
189             run all those B<_validate_*> messages and returns true if no error found.
190              
191             =head2 all_errors
192              
193             An array of the errors currently noted. combined with B<all_init_errors> and B<all_validation_errors>
194              
195             all errors including below methods are instance of error_class, default to L<MooX::Role::Validatable::Error>
196              
197             =head2 all_init_errors
198              
199             all errors on init
200              
201             =head2 all_validation_errors
202              
203             all errors on validation
204              
205             =head2 all_errors_by_severity
206              
207             order by severity
208              
209             =head2 primary_validation_error
210              
211             the first error of B<all_errors_by_severity>
212              
213             =head2 validation_methods
214              
215             A list of all validation methods available on this object.
216             This can be auto-generated from all methods which begin with
217             "_validate_" which is especially helpful in devleoping new validations.
218              
219             You may wish to set this list directly on the object, if
220             you create and validate a lot of static objects.
221              
222             =head2 error_class
223              
224             default to L<MooX::Role::Validatable::Error>, override by
225              
226             has '+error_class' => (is => 'ro', default => sub { 'My::Validatable::Error' });
227              
228             # or
229             ->new(error_class => 'My::Validatable::Error');
230              
231             =head1 AUTHOR
232              
233             Binary.com E<lt>fayland@binary.comE<gt>
234              
235             =head1 COPYRIGHT
236              
237             Copyright 2014- Binary.com
238              
239             =head1 LICENSE
240              
241             This library is free software; you can redistribute it and/or modify
242             it under the same terms as Perl itself.
243              
244             =head1 SEE ALSO
245              
246             =cut