NAME

MooX::Params::CompiledValidators - A Moo::Role for using Params::ValidationCompiler.

SYNOPSIS

    use Moo;
    use Types::Standard qw( Str );
    with 'MooX::Params::CompiledValidators';

    sub any_sub {
        my $self = shift;
        my $arguments = $self->validate_parameters(
            {
                $self->parameter(customer => $self->Required),
            },
            $_[0]
        );
        ...
    }

    # Implement a local version of the ValidationTemplates
    sub ValidationTemplates {
        return {
            customer => { type => Str },
        };
    }

DESCRIPTION

This role uses Params::ValidationCompiler to create parameter validators on a per method basis that can be used in the methods of your Moo or Moose projects.

The objective is to create a single set of validation criteria - ideally in a seperate role that can be used along side of this role - that can be used to consistently validate parameters throughout your application.

The validators created by Params::ValidationCompiler are cached after they are created first time, so they will only be created once.

Validation-Templates

The validation templates are roughly based on the templates described for Params::ValidationCompiler::validation_for().

Taken from Params::ValidationCompiler

type => $type

This argument is passed -as is- to validation_for().

It can be overridden from the extra parameter in the parameter() method.

default => $default

This argument is passed -as is- to validation_for().

It can be overridden from the extra parameter in the parameter() method.

Extra feature added

There is support for an extra key (that will not be passed to validation_for()):

store => $ref_to_scalar
    my $args = $self->validate_parameters(
        {
            $self->parameter( customer_id => $sef->Required, {store => \my $customer_id} ),
        },
        {@_}
    );
    # $customer_id is a usable value and $args->{customer_id} has the same value

The value should be a reference to a scalar, so we can store the value in that scalar.

One could argue that using (lexical) variables -instead of addressing keys of a locked hash- triggers the error caused by a typo at compile-time rather than at run-time.

NOTE: In order to keep the scope of the variable, where the value is stored, limited, the store attribute should only be used from the per method override option extra for $self->parameter().

$instance->Required

validation_for() uses the attribute optional so this returns 0

$instance->Optional

validation_for() uses the attribute optional so this returns 1

$instance->validate_parameters(@parameters)

Returns a (locked) hashref with validated parameters or die()s trying...

    my $self = shift;
    my $args = $self->validate_parameters(
        {
            customer_id => { type => Int, optional => 0 },
        },
        { @_ }
    );
    # we can now use $args->{customer_id}

NOTE: validate_parameters() supports the store attribute for te validation template.

Parameters

Positional:

1. $validation_templates

A hashref with the parameter-names as keys and the "validation templates" as values.

2. $values

A hashref with the actual parameter-name/value pairs that need to be validated.

Responses

Success (scalar context, recommended)

A locked hashref.

Success (list context, only if you need to manipulate the result)

A list that can be coerced into a hash.

Error

Anything Params::ValidationCompiler will throw for invalid values.

$instance->validate_positional_parameters(@parameters)

Like $instance->validate_parameters(), but now the pairs of name, validation_template are passed in an arrayref, that is split into lists of the names and templates. The parameters passed -as an array- will be validated against the templates-list, and the validated results are combined back into a hash with name/value pairs. This makes the programming interface almost the same for both named-parameters and positional-parameters.

Returns a (locked) hashref with validated parameters or die()s trying...

    my $self = shift;
    my $args = $self->validate_positional_parameters(
        [
            customer_id => { type => Int, optional => 0 },
        ],
        [ @_ ]
    );
    # we can now use $args->{customer_id}

NOTE: validate_positional_parameters() supports the store attribute for te validation template.

Parameters

Positional:

1. $validation_templates

A arrayref with pairs of parameter-names and "validation templates".

2. $values

A arrayref with the actual values that need to be validated.

Responses

Success (list context)

A list that can be coerced into a hash.

Success (scalar context)

A locked hashref.

Error

Anything Params::ValidationCompiler will throw for invalid values.

$instance->parameter($name, $required, $extra)

Returns a parameter_name, validation_template pair that can be used in the parameters argument hashref for Params::ValidationCompiler::validadion_for()

Parameters

Positional:

1. $name (Required)

The name of this parameter (it must be a kind of identifier: m{^\w+$})

2. $required (Optional)

One of $class->Required or $class->Optional but will default to $class->Required.

3. $extra (Optional)

This optional HashRef can contain the fields supported by the params parameter of validation_for(), even overriding the ones set by the $class->ValidationTemplates() for this $name - although optional is set by the previous parameter in this sub.

This parameter is mostly used for the extra feature to pass a lexically scoped variable to store the value in:

    $self->param(
        this_param => $self->Required,
        { store => \my $this_param },
    )

Responses

Success

A list of $parameter_name and $validation_template.

    (this_parm => { optional => 0, store => \my $this_param })

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See:

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

AUTHOR

(c) MMXXI - Abe Timmerman <abeltje@cpan.org>