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


Manual Reference Pages  -  MOOSEX::ROLE::PARAMETERIZED::TUTORIAL (3)

.ds Aq ’

NAME

MooseX::Role::Parameterized::Tutorial - why and how

CONTENTS

MOTIVATION

Roles are composable units of behavior. They are useful for factoring out functionality common to many classes from any part of your class hierarchy. See Moose::Cookbook::Roles::Recipe1 for an introduction to Moose::Role.

While combining roles affords you a great deal of flexibility, individual roles have very little in the way of configurability. Core Moose provides -alias for renaming methods and -excludes for ignoring methods. These options are primarily for resolving role conflicts. Depending on how much of a purist you are, these options are solely for resolving role conflicts. See Moose::Cookbook::Roles::Recipe2 for more about -alias and -excludes.

Because roles serve many different masters, they usually provide only the least common denominator of functionality. To empower roles further, more configurability than -alias and -excludes is required. Perhaps your role needs to know which method to call when it is done processing. Or what default value to use for its url attribute.

Parameterized roles offer a solution to these (and other) kinds of problems.

USAGE

with

The syntax of a class consuming a parameterized role has not changed from the standard with. You pass in parameters just like you pass in -alias and -excludes to ordinary roles (though your custom parameters do not get hyphens, since these are not core Moose composition parameters):



    with MyRole::InstrumentMethod => {
        method_name => dbh_do,
        log_to      => query.log,
    };



You can still combine parameterized roles. You just need to specify parameters immediately after the role they belong to:



    with (
        My::Parameterized::Role => {
            needs_better_example => 1,
        },
        My::Other::Role,
    );



We, like Moose itself, use Data::OptList to make sure that a list of role names and associated parameters is handled correctly.

parameter

Inside your parameterized role, you specify a set of parameters. This is exactly like specifying the attributes of a class. Instead of has in Moose you use the keyword parameter, but your parameters can use any options to has.



    parameter delegation => (
        isa       => HashRef|ArrayRef|RegexpRef,
        predicate => has_delegation,
    );



You do have to declare what parameters you accept, just like you have to declare what attributes you accept for regular Moose objects.

One departure from has is that we create a reader accessor for you by default. In other words, we assume is => ro. We create this reader for convenience because generally the parameterized role is the only consumer of the parameters object, so data hiding is not as important than in the general case of has in Moose. If you do not want an accessor, you can use is => bare.

role

role takes a block of code that will be used to generate your role with its parameters bound. Here is where you declare components that depend on parameters. You can declare attributes, methods, modifiers, etc. The first argument to the role is an object containing the parameters specified by with. You can access the parameters just like regular attributes on that object.

Each time you compose this parameterized role, the role {} block will be executed. It will receive a new parameter object and produce an entirely new role. That’s the whole point, after all.

Due to limitations inherent in Perl, you must declare methods with method name => sub { ... } instead of the usual sub name { ... }. Your methods may, of course, close over the parameter object. This means that your methods may use parameters however they wish!

USES

Ideally these will become fully-explained examples in something resembling Moose::Cookbook. But for now, only a braindump.
Configure a role’s attributes You can rename methods with core Moose, but now you can rename attributes. You can now also choose type, default value, whether it’s required, <B>traitsB>, etc.



    parameter traits => (
        isa     => ArrayRef,
        default => sub { [] },
    );

    parameter type => (
        isa     => Str,
        default => Any,
    );

    role {
        my $p = shift;

        has action => (
            traits => $p->traits,
            isa    => $p->type,
            ...
        );
    }



Inform a role of your class’ attributes and methods Core roles can only require methods with specific names chosen by the role. Now your roles can demand that the class specifies a method name you wish the role to instrument, or which attributes to dump to a file.



    parameter instrument_method => (
        isa      => Str,
        required => 1,
    );

    role {
        my $p = shift;
        around $p->instrument_method => sub { ... };
    }



Arbitrary execution choices Your role may be able to provide configuration in how the role’s methods operate. For example, you can tell the role whether to save intermediate states.



    parameter save_intermediate => (
        isa     => Bool,
        default => 0,
    );

    role {
        my $p = shift;
        method process => sub {
            ...
            if ($p->save_intermediate) { ... }
            ...
        };
    }



Deciding a backend Your role may be able to freeze and thaw your instances using YAML, JSON, Storable. Which backend to use can be a parameter.



    parameter format => (
        isa     => (enum [Storable, YAML, JSON]),
        default => Storable,
    );

    role {
        my $p = shift;
        if ($p->format eq Storable) {
            method freeze => \&Storable::freeze;
            method thaw   => \&Storable::thaw;
        }
        elsif ($p->format eq YAML) {
            method freeze => \&YAML::Dump;
            method thaw   => \&YAML::Load;
        }
        ...
    }



Additional validation Ordinary roles can require that its consumers have a particular list of method names. Since parameterized roles have direct access to its consumer, you can inspect it and throw errors if the consumer does not meet your needs.



    role {
        my $p    = shift;
        my %args = @_;
        my $consumer = $args{consumer};

        $consumer->find_attribute_by_name(stack)
            or confess "You must have a stack attribute";

        my $push = $consumer->find_method_by_name(push)
            or confess "You must have a push method";

        my $params = $push->parsed_signature->positional_params->params;
        @$params == 1
            or confess "Your push method must take a single parameter";

        $params->[0]->sigil eq $
            or confess "Your push parameter must be a scalar";

        ...
    }



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


perl v5.20.3 MOOSEX::ROLE::PARAMETERIZED::TUTORIAL (3) 2012-08-14

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