Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help

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

       version 1.11

       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::Comparable_CodeReuse 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::Restartable_AdvancedComposition 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"

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

       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,

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

       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" 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!

       Ideally these will become fully-explained examples in something
       resembling Moose::Cookbook. But for now,	only a brain dump.

       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, traits, 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};

		       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";


       Bugs may	be submitted through the RT bug	tracker
       Parameterized> (or

       There is	also a mailing list available for users	of this	distribution,
       at <>.

       There is	also an	irc channel available for users	of this	distribution,
       at "#moose" on "" <irc://>.

       Shawn M Moore <>

       This software is	copyright (c) 2008 by Shawn M Moore.

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

perl v5.32.1			  2019MooseX::Role::Parameterized::Tutorial(3)


Want to link to this manual page? Use this URL:

home | help