NAME

Params::Registry::Template - Template class for an individual parameter

VERSION

Version 0.04

SYNOPSIS

my $registry = Params::Registry->new(
    params => [
        # These constructs are passed into
        # the parameter template module.
        {
            # The name is consumed before
            # the object is constructed.
            name       => 'foo',

            # the type of individual values
            type       => 'Num',

            # the composite type with coercion
            composite  => 'NumberRange',

            # format string or sub for individual values
            format     => '%0.2f',

            # do not delete empty values
            empty      => 1,

            # For sets and ranges:
            # fetch range extrema or universal set
            universe   => \&_extrema_from_db,

            # supply an operation that complements the given
            # set/range against the extrema/universe
            complement => \&_range_complement,

            # supply a serialization function
            unwind     => \&_range_to_arrayref,
        },
        {
            name => 'bar',
            # Lengthy definitions can be reused.
            use  => 'foo',
        },
    ],
);

METHODS

new

This constructor is invoked by a factory method in Params::Registry. All arguments are optional unless specified otherwise.

registry

This back-reference to the registry is the only required argument. Since the template objects are constructed from a factory inside Params::Registry, it will be supplied automatically.

type

The Moose type of the individual values of the parameter. The default is Str.

composite

Specifies a composite type to envelop one or more distinct parameter values. If a composite type is specified, even single-valued parameters will be coerced into that composite type as if it was an ArrayRef. As such, composite types used in this field should be specified with coercions that expect ArrayRef, like so:

coerce FooBar => from ArrayRef => via { Foo::Bar->new(@{$_[0]}) };

# ...
{
    name      => 'foo',
    type      => 'Str',
    composite => 'FooBar',
    # ...
},
# ...
format

Either a format string or a subroutine reference depicting how scalar values ought to be serialized. The default value is %s.

depends

An ARRAY reference containing a list of parameters which must accompany this one.

conflicts

An ARRAY reference containing a list of parameters which must not be seen with this one.

consumes

For cascading parameters, an ARRAY reference containing a list of subsidiary parameters which are consumed to create it. All consumed parameters are automatically assumed to be in conflict, i.e., it makes no sense to have both a subsidiary parameter and one that consumes it in the input at the same time.

preproc

Supply a CODE reference to a function which coalesces values from the parameter in context (which may be empty) with other parameters specified by "consumes" and "depends". The function is expected to return a result which can be handled by "process": either the appropriate "composite" type (resulting in a no-op) or a list of valid primitives. The function is handed the following arguments:

$self

The Params::Registry::Template instance, to give the function (really a pseudo-method) access to its members.

current raw value

This will be an ARRAY reference containing zero or more elements, as supplied to the input. It will not be processed.

other parameters

All subsequent arguments to the "preproc" function will represent the set union of "consumes" and "depends". It will follow the sequence of keys specified in "consumes" followed by the sequence in "depends" minus those which already appear in "consumes".

It is important to note that these values will already have been processed, so they will be whatever (potentially "composite") type you specify. Make sure you author this function with this expectation.

The result(s) of "preproc" will be collected into an array and fed into "process". Use "depends" rather than "consumes" to supply other parameters without removing them from the resulting structure. Note that when "depends" is used in conjunction with "preproc", the dependencies must be acyclic.

"preproc" is called either just before "process" over supplied data, or in lieu of it.

Here is an example of "preproc" used to compose a set of parameters containing integers (e.g., from a legacy HTML form) into a DateTime object:

# ...
{
    name => 'year',
    type => 'Int',
    max  => 1,
},
{
    name => 'month',
    type => 'Int',
    max  => 1,
},
{
    name => 'day',
    type => 'Int',
    max  => 1,
},
{
    name => 'date',

    # this would be defined elsewhere with coercion from a
    # string that matches 'YYYY-MM-DD', for direct input.
    type => 'MyDateTimeType',

    # we don't want multiple values for this parameter.
    max  => 1,

    # in lieu of being explicitly defined in the input, this
    # parameter will be constructed from the following:
    consumes => [qw(year month day)],

    # and this is how it will happen:
    preproc => sub {
        my (undef, undef, $y, $m, $d) = @_;
        DateTime->new(
            year  => $y,
            month => $m,
            day   => $d,
        );
    },
},
# ...
min

The minimum number of values required for the given parameter. Set to 1 or higher to signal that the parameter is required. The default value is 0, meaning that the parameter is optional.

max

The maximum number of values acknowledged for the given parameter. Subsequent values will either be truncated to the right or shifted to the left, depending on the value of the "shift" property. Setting this property to 1 will force parameters to be scalar. The default is undef, which accepts an unbounded list of values.

shift

This boolean value determines the behaviour of input parameter values that exceed the parameter's maximum cardinality. The default behaviour is to truncate the list of values at the upper bound. Setting this bit instead causes the values for the ascribed parameter to be shifted off the left side of the list. This enables, for instance, dumb web applications to simply tack additional parameters onto the end of a query string without having to parse it.

empty

If a parameter value is undef or the empty string, the default behaviour is to act like it didn't exist in the input, thus pruning it from the resulting data and from the serialization. In the event that an empty value for a given parameter is meaningful, such as in expressing a range unbounded on one side, this bit can be set, and the "default" can be set to either undef or the empty string (or anything else).

default

This default value is passed through to the application only if the parameter in question is either missing or empty (if empty is set). Likewise if the final translation of the input value matches the default, it will not show up in the canonical serialization. Like Moose, is expected to be a CODE reference. The subroutine takes two arguments: this template object, and the Params::Registry::Instance object.

default => sub {
    my ($t, $i) = @_;
    # do something...
},
universe

For "Set" and "Range" parameters, this is a CODE reference which produces a universal set against which the input can be negated. In parameter serialization, there are often cases wherein a shorter string can be achieved by presenting the negated set and adding the parameter's name to the special parameter "complement" in Params::Registry. The subroutine can, for instance, query a database for the full set in question and return a type compatible with the parameter instance.

If you specify a universe, you must also specify a "complement".

complement

For "Set" and "Range" parameters, this CODE reference will need to do the right thing to produce the inverse set.

{
    # ...
    complement => sub {
        # assuming Set::Scalar
        my ($me, $universe) = @_;
        $me->complement($universe); },
    # ...
}

This field expects to be used in conjunction with "universe".

unwind

Specify a CODE reference to a subroutine which will turn the object into either a scalar or an ARRAY reference of scalars. To encourage code reuse, this function is applied before "reverse" despite the obvious ability to reverse the resulting list within the function.

The first argument to the subroutine is the template object itself, and the second is the value to be unwound. Subsequent arguments are the values of the parameters specified in "depends", if present.

sub my_unwind {
    my ($self, $obj, @depends) = @_;
    # ...
}

If you don't need any state data from the template, consider the following idiom:

{
    # ...
    # assuming the object is a Set::Scalar
    unwind => sub { [sort $_[1]->elements] },
    # ...
}

For multi-valued parameters, an optional second return value can be used to indicate that the special complement parameter should be set for this parameter. This is applicable, for instance, to the complement of a range, which would otherwise be impossible to serialize into a string.

reverse

For "Range" parameters, this bit indicates whether the input values should be interpreted and/or serialized in reverse order. This also governs the serialization of "Set" parameters.

process @VALS

Validate a list of individual parameter values and (optionally) construct a "composite" value.

unprocess $OBJ, @REST

Applies "unwind" to $OBJ to get an ARRAY reference, then "format" over each of the elements to get strings. In list context it will also return the flag from "unwind" indicating that the complement parameter should be set.

This method is called by "as_string" in Params::Registry::Instance and others to produce content which is amenable to serialization. As what happens there, the content of @REST should be the values of the parameters specified in "depends".

refresh

Refreshes stateful information like the universal set, if present.

AUTHOR

Dorian Taylor, <dorian at cpan.org>

SEE ALSO

LICENSE AND COPYRIGHT

Copyright 2013 Dorian Taylor.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 .

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.