The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Oogly - A Data validation idea that just might be ideal!

VERSION

version 0.31

SYNOPSIS

Oogly is a different approach to data validation, it attempts to simplify and centralize data validation rules to ensure DRY (don't repeat yourself) code. PLEASE NOTE! It is not the intent of this module to provide validation routines but instead to provide a simplistic validation flow-control and promote code reuse. The following is an example of that...

    use MyApp::Validation;
    my $app = MyApp::Validation->new(\%params);
    if ($app->validate('login', 'password')){
        ...
    }
    else {
        print join "\n", @{$app->errors};
    }

    package MyApp::Validation
    use Oogly qw/mixin field/;

    # define a mixin, a sortof template that can be included with other rules
    # by using the mixin directive
    mixin 'default' => {
        required    => 1,
        min_length  => 4,
        max_length  => 255
    };
    
    # define a data validation rule for parameter `login` using the default
    # mixin where the `login` must be between 4-255 characters long and have
    # at least one letter and number
    field 'login' => {
        label => 'user login',
        mixin => 'default',
        validation => sub {
            my ($self, $this, $params) = @_;
            my ($name, $value) = ($this->{label}, $params->{login});
            $self->error($this, "$name must contain at least one letter and number")
                unless ($value =~ /[a-zA-Z]/ || $value =~ /[0-9]/);
        }
    };
    
    # define a data validation rule for parameter `password` using the
    # previously defined field `login` as the mixin (template)
    field 'password' => {
        mixin_field => 'login',
        label => 'user password'
    };

And now for my second and final act, using Oogly outside of a package.

    #!/usr/bin/perl
    use Oogly qw/:all/;
    
    my $i = Oogly(
            mixins => {
                default => {
                    required    => 1,
                    min_length  => 4,
                    max_length  => 255
                }
            },
            fields => {
                login => {
                    label => 'user login',
                    mixin => 'default',
                    validation => sub {
                        my ($self, $this, $params) = @_;
                        my ($name, $value) = ($this->{name}, $params->{login});
                        $self->error($this, "field $name must contain at least one letter and number")
                            if ($value !~ /[a-zA-Z]/ && $value !~ /[0-9]/);
                    }
                },
                password => {
                    mixin_field => 'login',
                    label => 'user password'
                }
            },
    );
    
    # Important, store the new instance created by the $i->setup function
    $o = $i->setup({ login => 'root', password => '...' });
    
    if ($o->validate) {
        ...
    }

METHODS

new

The new method instantiates a new Oogly or Oogly package instance.

setup

The setup method is magical.

field

The field function defines the validation rules for the specified parameter it is named after. e.g. field 'some_data' => {...}, validates against the value of the hash reference where the key is `some_data`.

    field 'some_param' => {
        mixin => 'default',
        validation => sub {
            my ($v, $this, $params) = @_;
            $v->error($this, "...")
                if ...
        }
    };

    Fields are comprised of specific directives, those directives are as follows:
    name: The name of the field (auto set)
    value: The value of the parameter matching the name of the field (auto set)
    mixin: The template to be used to copy directives from
    
    mixin 'template' => {
        required => 1
    };
    
    field 'a_field' => {
        mixin => 'template'
    }
    
    mixin_field: The field to be used as a mixin(template) to copy directives from
    
    field 'a_field' => {
        required => 1,
        min_length => 2,
        max_length => 10
    };
    
    field 'b_field' => {
        mixin_field => 'a_field'
    };
    
    validation: A validation routine that returns true or false
    
    field '...' => {
        validation => sub {
            my ($self, $field, $all_parameters) = @_;
            return 1
        }
    };
    
    errors: The collection of errors encountered during processing (auto set arrayref)
    label: An alias for the field name, something more human-readable
    error: A custom error message, displayed instead of the generic ones
    required : Determines whether the field is required or not, takes 1/0 true of false
    min_length: Determines the maximum length of characters allowed
    max_length: Determines the minimum length of characters allowed
    ref_type: Determines whether the field value is a valid perl reference variable
    regex: Determines whether the field value passed the regular expression test
    
    field 'c_field' => {
        label => 'a field labeled c',
        error => 'a field labeled c cannot ',
        required => 1,
        min_length => 2,
        max_length => 25,
        ref_type => 'array',
        regex => '^\d+$'
    };
    
    filter: An alias for the filters directive, see filter method for filter names
    filters: Set filters to manipulate the data before validation
    
    field 'd_field' => {
        ...,
        filters => [
            'trim',
            'strip'
        ]
    };
    
    field 'e_field' => {
        filter => 'strip'
    };
    
    field 'f_field' => {
        filters => [
            'trim',
            sub {
                $_[0] =~ s/(abc)|(123)//;
            }
        ]
    };

mixin

The mixin function defines validation rule templates to be later reused by more specifically defined fields.

    mixin 'default' => {
        required    => 1,
        min_length  => 4,
        max_length  => 255
    };

error

The error function is used to set and/or retrieve errors encountered or set during validation. The error function with no parameters returns the error message arrayref which can be used to output a single concatenated error message a with delimeter.

    $self->error() # returns an arrayref of errors
    join '<br/>', @{$self->error()}; # html-break delimeted errors
    $self->error('some_param'); # show parameter-specific error messages arrayref
    $self->error($this, "$name must conform ..."); # set error, see `field` function

errors

The errors function is a synonym for the error function.

check_mixin

The check_mixin function is used internally to validate the defined keys and values of mixins.

check_field

The check_field function is used internally to validate the defined keys and values of fields.

use_mixin

The use_mixin function sequentially applies defined mixin parameteres (as templates)to the specified field.

use_mixin_field

The use_mixin_field function copies the properties (directives) of a specified field to the target field processing copied mixins along the way.

validate

The validate function sequentially checks the passed-in field names against their defined validation rules and returns 0 or 1 based on the existence of errors.

basic_validate

The basic_validate function processes the pre-defined contraints e.g., required, min_length, max_length, etc.

basic_filter

The basic_filter function processes the pre-defined filters e.g., trim, strip, digit, alpha, numeric, alphanumeric, uppercase, lowercase, titlecase, or custom etc.

Oogly

The Oogly method encapsulates fields and mixins and returns an Oogly instance for further validation. This method exist for situations where Oogly is use outside of a specific validation package.

    my $i = Oogly(
            mixins => {
                    'default' => {
                            required => 1
                    }
            },
            fields => {
                    'test1' => {
                            mixin => 'default'
                    }
            },
    );
    
    # Important store the new instance
    $o = $i->setup({ test1 => '...' });
    
    if ($o->validate('test1')) {
        ...
    }

AUTHOR

Al Newkirk <awncorp@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2010 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.