GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
Params::Validate::Dependencies::Extending(3) User Contributed Perl Documentation Params::Validate::Dependencies::Extending(3)

Params::Validate::Dependencies::Extending

How to extend Params::Validate::Dependencies, and a discussion of its internals.

Before even thinking about extending this module you should understand references, in particular code-references and closures, and also understand objects in perl.

If you've read the documentation for Params::Validate::Dependencies and Data::Domain::Dependencies, then you'd think that they return a code-ref which is a closure over the original arguments, and that they're implemented something like this:

  sub any_of {
    my @options = @_;
    return sub {
      my $hashref = shift;
      ... do stuff with @options and $hashref ...
    }
  }

In version 1, that was exactly what was happening. But then I wanted to make them self-documenting.

Now, they still return a code-ref, but that code-ref is blessed into a class - Params::Validate::Dependencies::any_of in the case of the closures generated by "any_of" - so that I can attach a little bit of extra metadata. They now look something like this:

  sub any_of {
    my @options = @_;
    bless sub {
      ... some extra stuff ...
      my $hashref = shift;
      ... do stuff with @options and $hashref ...
    }, 'Params::Validate::Dependencies::any_of';
  }

There are four such classes, one for each of the *_of functions.

Each of those four classes is a sub-class of Params::Validate::Dependencies::Documenter. When you call Params::Validate::Dependencies::document() and pass it one of those objects, it calls the object's "_document" method. That puts P::V::D into "documentation mode" by setting a global variable to the object itself, and then executes the object's underlying code-ref.

In the example above, where it says "... some extra stuff ...", we actually have this:

  if($Params::Validate::Dependencies::DOC) {
    return $Params::Validate::Dependencies::DOC->_doc_me(list => \@options);
  }

so, now that <$DOC> has a value, the code-ref doesn't bother validating anything, it instead calls its "_doc_me" method, and passes it the options that the closure was originally created with.

Finally, "_doc_me", which now has both the data that was originally closed over, and the object itself, it can construct a useful string of documentation. To do this it gets the name of the original factory function by calling the object's "name" method - in the case of a Params::Validate::Dependencies::any_of object this returns 'any_of' - and, so that it can use 'and' or 'or' when constructing lists, it gets that by calling the "join_with" method.

It then iterates over the original list of options, scalars first followed by code-reffy objects, recursing into objects and getting them to document themselves.

The end result of that, given a code-ref created thus:

  any_of(
    qw(alpha beta),
    all_of(
      qw(foo bar),
      none_of('barf')
    ),
    one_of(qw(quux garbleflux))
  )

You will get back documentation like this:

  any of ('alpha', 'beta', all of ('foo', 'bar' and none of ('barf')) or one of ('quux' or 'garbleflux'))

which is admittedly not perfect but is better than having to write the blasted stuff yourself.

If you can't be bothered with making your validators self-documenting, then you can just have them return a closure and be done with it:

  sub two_of {
    my @options = @_;
    return sub {
      my $hashref = shift;
      my $count = 0;
      foreach my $option (@options) {
        $count++ if(
          (!ref($option) && exists($hashref->{$option})) ||
          (ref($option) && $option->($hashref))
        );
      }
      return ($count == 2);
    }
  }

There is an example of this in t/05-extra-validator-without-doco.t. In fact it's this very example.

If you want to do the full-fat implementation complete with auto-doc, then you will need to implement one teeny-tiny class, as well as modify your factory function to return an object of that class and to look out for "documentation mode" being turned on. The example above would be modifed thus:

  sub two_of {
    my @options = @_;
    return bless sub {
      if($Params::Validate::Dependencies::DOC) {
        return $Params::Validate::Dependencies::DOC->_doc_me(list => \@options);
      }
      ...
    }, 'Params::Validate::Dependencies::two_of'
  }

and the corresponding class would look like:

  package Params::Validate::Dependencies::two_of;
  use base qw(Params::Validate::Dependencies::Documenter);
  sub join_with { return 'or'; }
  sub name { return 'two_of'; }

It is suggested that you combine class and function together, and have it export the function, as can be seen in the example in t/lib/Params/Validate/Dependencies/two_of.pm, which is used in t/06-extra-validator-with-doco.t.

If the "_doc_me" method described above can't cope with your new validation function then your class need not bother implementing the "name" or "join_with" methods, but your function must, when <$Params::Validate::Dependencies::DOC> is set, return a string. Anything that you want the "exclusively()" validator to pay attention to needs to be single quoted, with any embedded single quotes preceded by a back-slash.

Best practice is to return something that looks very similar to how your function was invoked in the first place.

For an example see how the "exclusively()" function documents itself.

You may not write your own validators or classes for the following, as they are implemented by Params::Validate::Dependencies itself. If you try implementing them, strange things may happen:
none_of
one_of
any_of
all_of
exclusively

Params::Validate::Dependencies

Data::Domain::Dependencies

<git://github.com/DrHyde/perl-modules-Params-Validate-Dependencies.git>

<https://github.com/DrHyde/perl-modules-Params-Validate-Dependencies/>

Copyright 2016 David Cantrell <david@cantrell.org.uk>

This documentation is free-as-in-speech software. It may be used, distributed, and modified under the terms of the Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License, whose text you may read at <http://creativecommons.org/licenses/by-sa/2.0/uk/>.

This documentation is also free-as-in-mason.
2016-10-05 perl v5.32.1

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.