Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

780 lines (535 sloc) 22.992 kb
NAME
Validation::Class - Self-Validating Object System and Data Validation
Framework
VERSION
version 7.86
SYNOPSIS
package MyApp::User;
use Validation::Class;
mixin basic => {
required => 1,
max_length => 255,
filters => [qw/trim strip/]
};
field login => {
mixin => 'basic',
min_length => 5
};
field password => {
mixin => 'basic',
min_length => 5,
min_symbols => 1
};
package main;
my $user = MyApp::User->new(login => 'admin', password => 'secr3t');
unless ($user->validate('login', 'password')) {
# do something with the errors,
# e.g. print $user->errors_to_string
}
1;
Validation::Class is a data validation framework and simple object
system. It allows you to model data and construct objects with focus on
structure, reusability and data validation. It expects user input errors
(without dying), validation only occurs when you ask it to.
Validation::Class classes are designed to ensure consistency and promote
reuse of data validation rules.
Validation::Class::Intro will help you better understand the framework's
rationale and typical use-cases while Validation::Class::Prototype will
help you discover all the bells-and-whistles included in the framework.
DESCRIPTION
Validation::Class is much more than a robust data validation framework,
in-fact it is more of a data modeling framework and can be used as an
alternative to minimalistic object systems such as Moo, Mo, etc.
Validation::Class aims to provide the building blocks for easily
definable self-validating data models. For more information on the
validation class object system, review "the object system" section.
Validation classes are typically defined using the following keywords:
* field - a field is a data validation rule
* mixin - a field template
* directive - a field/mixin rule attribute
* filter - a directive which transforms the field parameter value
* method - a self-validating sub-routine
* object - a simple object builder
To keep your class namespace clean and free from pollution, all
inherited functionality is configured on your class' prototype (a cached
class configuration object) which leaves you free to create and
overwrite method names in your class without breaking the
Validation::Class framework, this all happens much in the same way Moose
uses it's MOP (meta-object-protocol) having most of the framework
functionality residing in the Moose::Meta namespace. For more
information on the validation class prototype, review "the prototype
class" section.
One very important (and intentional) difference between Moose/Moose-like
systems and Validation::Class classes is in the handling of errors.
There are generally two types of errors that occur in an application,
user-errors which are expected and should be handled and reported, and
system-errors which are unexpected and should cause the application to
terminate or otherwise handle the exception. It is not always desired
and/or appropriate to crash from a failure to validate a particular
parameter. In Validation::Class, the application is not terminated or
validate automatically unless you configure it to.
Additionally, please review the Validation::Class::Intro for a more
in-depth understanding of how to leverage Validation::Class.
KEYWORDS
attribute
The attribute keyword (or has) creates a class attribute. This is only a
minimalistic variant of what you may have encountered in other object
systems such as Moose, Mouse, Moo, Mo, etc.
package MyApp::User;
use Validate::Class;
attribute 'bothered' => 1;
attribute 'attitude' => sub {
return $self->bothered ? 1 : 0
};
1;
The attribute keyword takes two arguments, the attribute name and a
constant or coderef that will be used as its default value.
build
The build keyword (or bld) registers a coderef to be run at
instantiation much in the same way the common BUILD routine is used in
modern-day OO systems.
package MyApp::User;
use Validation::Class;
build sub {
my ($self, %args) = @_;
# ... do something
};
# die like a Moose
use Carp;
build sub {
my ($self, %args) = @_;
my @attributes = qw();
foreach my $attribute (@attributes) {
confess "Attribute ($attribute) is required"
unless $self->$attribute;
}
};
The build keyword takes one argument, a coderef which is passed the
instantiated class object.
directive
The directive keyword (or dir) creates custom validator directives to be
used in your field definitions. It is a means of extending the
pre-existing directives table before runtime and is ideal for creating
custom directive extension packages to be used in all your classes.
package MyApp::Directives;
use Validation::Class;
use Data::Validate::Email;
directive 'is_email' => sub {
my ($dir, $value, $field, $self) = @_;
my $validator = Data::Validate::Email->new;
unless ($validator->is_email($value)) {
my $handle = $field->{label} || $field->{name};
$field->{errors}->add("$handle must be a valid email address");
return 0;
}
return 1;
};
package MyApp::User;
use Validate::Class;
use MyApp::Directives;
field 'email' => {
is_email => 1,
...
};
1;
The directive keyword takes two arguments, the name of the directive and
a coderef which will be used to validate the associated field. The
coderef is passed four ordered parameters, the value of directive, the
value of the field (parameter value), the field object (hashref), and
the instantiated class object. The validator MUST return true or false.
Additionally, if you only desire to extend the list of acceptable
directives, you can create a no-op by simply returning true, e.g.:
directive 'new_addition' => sub {1};
field
The field keyword (or fld) creates a data validation rule for reuse and
validation in code. The field name should correspond with the parameter
name expected to be passed to your validation class.
package MyApp::User;
use Validation::Class;
field 'login' => {
required => 1,
min_length => 1,
max_length => 255,
...
};
The field keyword takes two arguments, the field name and a hashref of
key/values pairs known as directives.
The field keyword also creates accessors which provide easy access to
the field's corresponding parameter value(s). Accessors will be created
using the field's name as a label having any special characters replaced
with an underscore.
field 'login' => {
required => 1,
min_length => 1,
max_length => 255,
...
};
field 'preference.send_reminders' => {
required => 1,
max_length => 1,
...
};
my $value = $self->login;
$self->login($new_value);
$self->preference_send_reminders;
Protip: Field directives are used to validate scalar and array data.
Don't use fields to store and validate objects. Please see the *has*
keyword instead or use an object system with type constraints like
Moose.
filter
The filter keyword (or flt) creates custom filters to be used in your
field definitions. It is a means of extending the pre-existing filters
table before runtime and is ideal for creating custom directive
extension packages to be used in all your classes.
package MyApp::Directives;
use Validation::Class;
filter 'flatten' => sub {
$_[0] =~ s/[\t\r\n]+/ /g;
$_[0] # return
};
package MyApp::User;
use Validate::Class;
use MyApp::Directives;
field 'description' => {
filters => ['trim', 'flatten'],
...
};
1;
The filter keyword takes two arguments, the name of the filter and a
coderef which will be used to filter the value the associated field. The
coderef is passed the value of the field and that value MUST be operated
on directly. The coderef should also return the transformed value.
method
The method keyword (or mth) is used to create an auto-validating method.
Similar to method signatures, an auto-validating method can leverage
pre-existing validation rules and profiles to ensure a method has the
required data necessary to proceed.
package MyApp::User;
use Validation::Class;
method 'register' => {
input => ['name', '+email', 'login', '+password'],
output => ['+id'], # optional output validation, dies on failure
using => sub {
my ($self, @args) = @_;
# .... do something registrationy
$self->id(...); # set the ID field for output validation
return $self;
}
};
package main;
my $user = MyApp::User->new(params => $params);
if ($user->register) {
...
}
1;
The method keyword takes two arguments, the name of the method to be
created and a hashref of required key/value pairs. The hashref must have
an "input" variable whose value is either an arrayref of fields to be
validated, or a constant value which matches a validation profile name.
The hashref must also have a "using" variable whose value is a coderef
which will be executed upon successfully validating the input. Whether
and what the method returns is yours to decide.
Optionally the required hashref can have an "output" variable whose
value is either an arrayref of fields to be validated, or a constant
value which matches a validation profile name which will be used to
perform data validation after the coderef has been executed. Please note
that output validation failure will cause the program to die, the
premise behind this decision is based on the assumption that given
successfully validated input a routine's output should be predictable
and if an error occurs it is most-likely a program error as opposed to a
user error.
See the ignore_failure and report_failure switch to control how method
input validation failures are handled.
mixin
The mixin keyword (or mxn) creates a validation rules template that can
be applied to any field using the mixin directive. Mixin directives are
processed first so existing field directives will override the mixed-in
directives.
package MyApp::User;
use Validation::Class;
mixin 'constrain' => {
required => 1,
min_length => 1,
max_length => 255,
...
};
# e.g.
field 'login' => {
mixin => 'constrain',
...
};
The mixin keyword takes two arguments, the mixin name and a hashref of
key/values pairs known as directives.
profile
The profile keyword (or pro) stores a validation profile (coderef) which
as in the traditional use of the term is a sequence of validation
routines that validate data relevant to a specific action.
package MyApp::User;
use Validation::Class;
profile 'signup' => sub {
my ($self, @args) = @_;
# ... do other stuff
return $self->validate(qw(
+name
+email
+email_confirmation
-login
+password
+password_confirmation
));
};
package main;
my $user = MyApp::User->new(params => $params);
unless ($user->validate_profile('signup')) {
die $user->errors_to_string;
}
The profile keyword takes two arguments, a profile name and coderef
which will be used to execute a sequence of actions for validation
purposes.
METHODS
new
The new method instantiates a new class object, it performs a series of
actions (magic) required for the class function properly, and for that
reason, this method should never be overridden. Use the build keyword to
hooking into the instantiation process.
package MyApp;
use Validation::Class;
# optionally
build sub {
my ($self, @args) = @_; # is instantiated
};
package main;
my $app = MyApp->new;
...
prototype
The prototype method (or proto) returns an instance of the associated
class prototype. The class prototype is responsible for manipulating and
validating the data model (the class). It is not likely that you'll need
to access this method directly, see "THE PROTOTYPE CLASS" in
Validation::Class.
package MyApp;
use Validation::Class;
package main;
my $app = MyApp->new;
my $prototype = $app->prototype;
...
THE PROTOTYPE CLASS
This module provides mechanisms (sugar functions to model your data)
which allow you to define self-validating classes. Each class you create
is associated with a *prototype* class which provides data validation
functionality and keeps your class' namespace free from pollution,
please see Validation::Class::Prototype for more information on specific
methods, and attributes.
All derived classes will have a prototype-class attached to it which
does all the heavy lifting (regarding validation and error handling).
The prototype injects a few proxy methods into your class which are
basically aliases to your prototype class methods, however it is
possible to access the prototype directly using the proto/prototype
methods.
package MyApp::User;
use Validation::Class;
package main;
my $user = MyApp::User->new;
my $proto = $user->prototype;
$proto->error_count # same as calling $self->error_count
THE OBJECT SYSTEM
All derived classes will benefit from the light-weight, straight-forward
and simple object system Validation::Class provides. The conventional
constructor "new" should be used to instantiate a new object, and the
"bld"/"build" keywords can be used to hook into the instantiation
process. Your classes can be configured to cooperate with an existing
design or modern OO framework like Moose, Mouse, Moo, etc. The following
example explains how to setup a Validation::Class class in cooperation
with Moose (while this example focuses on Moose, the approach is the
same regardless of the existing system):
# USING MOOSE AS YOUR PRIMARY OO SYSTEM
package MyApp;
use Moose;
use Validation::Class '!has'; # in cooperative mode, dont export has()
# you must run initialization routines yourself ...
# specifying it in a BUILD routine will run it automatically
sub BUILD {
my ($self, $args) = @_;
$self->initialize_validator(
params => $args->{params}
);
}
field login => {
min_length => 5
max_length => 50
};
field password => {
min_length => 8,
min_symbols => 1
max_length => 50
};
# USING MOOSE AS YOUR SECONDARY/BACKUP OO SYSTEM
package MyApp;
use Validation::Class '!has'; # avoids has() keyword clash
use Moose;
field login => {
min_length => 5
max_length => 50
};
field password => {
min_length => 8,
min_symbols => 1
max_length => 50
};
has database => (
is => 'rw',
isa => 'DBI::db',
...
);
1;
This cooperation works by simply detecting the existence of a method
named "new", the name traditionally reserved for a class constructor
which if detected signals Validation::Class to install a method named
"initialize" as opposed to installing its own constructor. The installed
method, "initialize", encapsulates the functionality which prepares the
class for interaction with its corresponding prototype class, this
function must be called before using the Validation::Class features
provided. If this concept isn't clear to you you needn't worry as this
is very low-level, all you need you understand is that Validation::Class
will install a constructor or a method named initialize if a constructor
already exists, either way, the installed method should be called before
executing methods on the class.
As previously stated, Validation::Class injects a few proxy methods into
your class which are basically aliases to your prototype class methods.
You can find additional information on the prototype class and its
method at Validation::Class::Prototype. The following is a list of
*proxy* methods, methods which are injected into your class as shorthand
to methods defined in the prototype class (these methods are
overridden):
class
$self->class;
See "class" in Validation::Class::Prototype for full documentation.
clear_queue
$self->clear_queue;
See "clear_queue" in Validation::Class::Prototype for full
documentation.
error_count
$self->error_count;
See "error_count" in Validation::Class::Prototype for full
documentation.
error_fields
$self->error_fields;
See "error_fields" in Validation::Class::Prototype for full
documentation.
errors
$self->errors;
See "errors" in Validation::Class::Prototype for full documentation.
head2 errors_to_string
$self->errors_to_string;
See "errors_to_string" in Validation::Class::Prototype for full
documentation.
get_errors
$self->get_errors;
See "get_errors" in Validation::Class::Prototype for full documentation.
get_fields
$self->get_fields;
See "get_fields" in Validation::Class::Prototype for full documentation.
get_params
$self->get_params;
See "get_params" in Validation::Class::Prototype for full documentation.
fields
$self->fields;
See "fields" in Validation::Class::Prototype for full documentation.
filtering
$self->filtering;
See "filtering" in Validation::Class::Prototype for full documentation.
ignore_failure
$self->ignore_failure;
See "ignore_failure" in Validation::Class::Prototype for full
documentation.
ignore_unknown
$self->ignore_unknown;
See "ignore_unknown" in Validation::Class::Prototype for full
documentation.
param
$self->param;
See "param" in Validation::Class::Prototype for full documentation.
params
$self->params;
See "params" in Validation::Class::Prototype for full documentation.
plugin
$self->plugin;
See "plugin" in Validation::Class::Prototype for full documentation.
queue
$self->queue;
See "queue" in Validation::Class::Prototype for full documentation.
report_failure
$self->report_failure;
See "report_failure" in Validation::Class::Prototype for full
documentation.
report_unknown
$self->report_unknown;
See "report_unknown" in Validation::Class::Prototype for full
documentation.
reset_errors
$self->reset_errors;
See "reset_errors" in Validation::Class::Prototype for full
documentation.
reset_fields
$self->reset_fields;
See "reset_fields" in Validation::Class::Prototype for full
documentation.
reset_params
$self->reset_params;
See "reset_params" in Validation::Class::Prototype for full
documentation.
set_errors
$self->set_errors;
See "set_errors" in Validation::Class::Prototype for full documentation.
set_fields
$self->set_fields;
See "set_fields" in Validation::Class::Prototype for full documentation.
set_params
$self->set_params;
See "set_params" in Validation::Class::Prototype for full documentation.
set_method
$self->set_method;
See "set_method" in Validation::Class::Prototype for full documentation.
stash
$self->stash;
See "stash" in Validation::Class::Prototype for full documentation.
validate
$self->validate;
See "validate" in Validation::Class::Prototype for full documentation.
validate_method
$self->validate_method;
See "validate_method" in Validation::Class::Prototype for full
documentation.
validate_profile
$self->validate_profile;
See "validate_profile" in Validation::Class::Prototype for full
documentation.
EXTENDING VALIDATION::CLASS
Validation::Class does NOT provide method modifiers but can be easily
extended with Class::Method::Modifiers.
before
before foo => sub { ... };
See "before method(s) => sub { ... }" in Class::Method::Modifiers for
full documentation.
around
around foo => sub { ... };
See "around method(s) => sub { ... }" in Class::Method::Modifiers for
full documentation.
after
after foo => sub { ... };
See "after method(s) => sub { ... }" in Class::Method::Modifiers for
full documentation.
SEE ALSO
Additionally you may want to look elsewhere for your data validation
needs so the following is a list of recommended validation
libraries/frameworks you might do well to look into. Validate::Tiny is
nice for simple use-cases, it has virtually no dependencies and solid
test coverage. Data::Verifier is a great approach towards adding robust
validation options to your existing Moose classes. Also, I have also
heard some good things about Data::FormValidator as well.
AUTHOR
Al Newkirk <anewkirk@ana.io>
COPYRIGHT AND LICENSE
This software is copyright (c) 2011 by Al Newkirk.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
Jump to Line
Something went wrong with that request. Please try again.