Initial Commit
This commit is contained in:
87
database/perl/vendor/lib/MooseX/Role/Parameterized/Extending.pod
vendored
Normal file
87
database/perl/vendor/lib/MooseX/Role/Parameterized/Extending.pod
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
# PODNAME: MooseX::Role::Parameterized::Extending
|
||||
# ABSTRACT: extending MooseX::Role::Parameterized roles
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
MooseX::Role::Parameterized::Extending - extending MooseX::Role::Parameterized roles
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.11
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
There are heaps of useful modules in the C<MooseX> namespace that you can use
|
||||
to make your roles more powerful. However, they do not always work out of the
|
||||
box with L<MooseX::Role::Parameterized>, but it's fairly straight-forward to
|
||||
achieve the functionality you desire.
|
||||
|
||||
L<MooseX::Role::Parameterized> was designed to be as extensible as the rest of
|
||||
L<Moose>, and as such it is possible to apply custom traits to both the
|
||||
parameterizable role or the ordinary roles they generate. In this example, we
|
||||
will look at applying the fake trait C<MooseX::MagicRole> to a parameterizable
|
||||
role.
|
||||
|
||||
First we need to define a new metaclass for our parameterizable role.
|
||||
|
||||
package MyApp::Meta::Role::Parameterizable;
|
||||
use Moose;
|
||||
extends 'MooseX::Role::Parameterized::Meta::Role::Parameterizable';
|
||||
with 'MooseX::MagicRole';
|
||||
|
||||
This is a class (observe that it uses L<Moose>, not L<Moose::Role>) which
|
||||
extends the class which governs parameterizable roles.
|
||||
L<MooseX::Role::Parameterized::Meta::Role::Parameterizable> is the metaclass
|
||||
that packages using L<MooseX::Role::Parameterized> receive by default.
|
||||
|
||||
Note that the class we are extending,
|
||||
L<MooseX::Role::Parameterized::Meta::Role::ParameterizB<I<able>>|MooseX::Role::Parameterized::Meta::Role::Parameterizable>,
|
||||
is entirely distinct from the similarly-named class which governs the
|
||||
ordinary roles that parameterized roles generate. An instance of
|
||||
L<MooseX::Role::Parameterized::Meta::Role::ParameterizB<I<ed>>|MooseX::Role::Parameterized>
|
||||
represents a role with its parameters already bound.
|
||||
|
||||
Now we can take advantage of our new subclass by specifying that we want to use
|
||||
C<MyApp::Meta::Role::Parameterizable> as our metaclass when importing
|
||||
L<MooseX::Role::Parameterized>:
|
||||
|
||||
package MyApp::Role;
|
||||
use MooseX::Role::Parameterized -metaclass => 'MyApp::Meta::Role::Parameterizable';
|
||||
|
||||
role {
|
||||
...
|
||||
}
|
||||
|
||||
And there you go! C<MyApp::Role> now has the C<MooseX::MagicRole> trait applied.
|
||||
|
||||
=head1 NAME
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Role-Parameterized>
|
||||
(or L<bug-MooseX-Role-Parameterized@rt.cpan.org|mailto:bug-MooseX-Role-Parameterized@rt.cpan.org>).
|
||||
|
||||
There is also a mailing list available for users of this distribution, at
|
||||
L<http://lists.perl.org/list/moose.html>.
|
||||
|
||||
There is also an irc channel available for users of this distribution, at
|
||||
L<C<#moose> on C<irc.perl.org>|irc://irc.perl.org/#moose>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shawn M Moore <code@sartak.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
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.
|
||||
|
||||
=cut
|
||||
57
database/perl/vendor/lib/MooseX/Role/Parameterized/Meta/Role/Parameterized.pm
vendored
Normal file
57
database/perl/vendor/lib/MooseX/Role/Parameterized/Meta/Role/Parameterized.pm
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package MooseX::Role::Parameterized::Meta::Role::Parameterized;
|
||||
# ABSTRACT: metaclass for parameterized roles
|
||||
|
||||
our $VERSION = '1.11';
|
||||
|
||||
use Moose;
|
||||
extends 'Moose::Meta::Role';
|
||||
with 'MooseX::Role::Parameterized::Meta::Trait::Parameterized';
|
||||
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
no Moose;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
MooseX::Role::Parameterized::Meta::Role::Parameterized - metaclass for parameterized roles
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.11
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is the metaclass for parameterized roles; that is, parameterizable roles
|
||||
with their parameters bound. See
|
||||
L<MooseX::Role::Parameterized::Meta::Trait::Parameterized> which has all the guts.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Role-Parameterized>
|
||||
(or L<bug-MooseX-Role-Parameterized@rt.cpan.org|mailto:bug-MooseX-Role-Parameterized@rt.cpan.org>).
|
||||
|
||||
There is also a mailing list available for users of this distribution, at
|
||||
L<http://lists.perl.org/list/moose.html>.
|
||||
|
||||
There is also an irc channel available for users of this distribution, at
|
||||
L<C<#moose> on C<irc.perl.org>|irc://irc.perl.org/#moose>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shawn M Moore <code@sartak.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
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.
|
||||
|
||||
=cut
|
||||
262
database/perl/vendor/lib/MooseX/Role/Parameterized/Meta/Trait/Parameterizable.pm
vendored
Normal file
262
database/perl/vendor/lib/MooseX/Role/Parameterized/Meta/Trait/Parameterizable.pm
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
package MooseX::Role::Parameterized::Meta::Trait::Parameterizable;
|
||||
# ABSTRACT: trait for parameterizable roles
|
||||
|
||||
our $VERSION = '1.11';
|
||||
|
||||
use Moose::Role;
|
||||
use MooseX::Role::Parameterized::Meta::Role::Parameterized;
|
||||
use MooseX::Role::Parameterized::Parameters;
|
||||
use Module::Runtime 'use_module';
|
||||
use namespace::autoclean;
|
||||
|
||||
has parameterized_role_metaclass => (
|
||||
is => 'ro',
|
||||
isa => 'ClassName',
|
||||
default => 'MooseX::Role::Parameterized::Meta::Role::Parameterized',
|
||||
);
|
||||
|
||||
has parameters_class => (
|
||||
is => 'ro',
|
||||
isa => 'ClassName',
|
||||
default => 'MooseX::Role::Parameterized::Parameters',
|
||||
);
|
||||
|
||||
has parameters_metaclass => (
|
||||
is => 'rw',
|
||||
isa => 'Moose::Meta::Class',
|
||||
lazy => 1,
|
||||
builder => '_build_parameters_metaclass',
|
||||
handles => {
|
||||
has_parameter => 'has_attribute',
|
||||
add_parameter => 'add_attribute',
|
||||
construct_parameters => 'new_object',
|
||||
},
|
||||
predicate => '_has_parameters_metaclass',
|
||||
);
|
||||
|
||||
has role_generator => (
|
||||
is => 'rw',
|
||||
isa => 'CodeRef',
|
||||
predicate => 'has_role_generator',
|
||||
);
|
||||
|
||||
sub _build_parameters_metaclass {
|
||||
my $self = shift;
|
||||
|
||||
return $self->parameters_class->meta->create_anon_class(
|
||||
superclasses => [$self->parameters_class],
|
||||
);
|
||||
}
|
||||
|
||||
my $package_counter = 0;
|
||||
sub generate_role {
|
||||
my $self = shift;
|
||||
my %args = @_;
|
||||
|
||||
my $parameters = blessed($args{parameters})
|
||||
? $args{parameters}
|
||||
: $self->construct_parameters(%{ $args{parameters} });
|
||||
|
||||
confess "A role generator is required to apply parameterized roles (did you forget the 'role { ... }' block in your parameterized role '".$self->name."'?)"
|
||||
unless $self->has_role_generator;
|
||||
|
||||
my $parameterized_role_metaclass = $self->parameterized_role_metaclass;
|
||||
use_module($parameterized_role_metaclass);
|
||||
|
||||
my $package = $args{package};
|
||||
unless ($package) {
|
||||
$package_counter++;
|
||||
$package = $self->name . '::__ANON__::SERIAL::' . $package_counter;
|
||||
}
|
||||
my $role = $parameterized_role_metaclass->create(
|
||||
$package,
|
||||
genitor => $self,
|
||||
parameters => $parameters,
|
||||
);
|
||||
|
||||
local $MooseX::Role::Parameterized::CURRENT_METACLASS = $role;
|
||||
|
||||
# The generate_role method is being called directly by things like
|
||||
# MooseX::ClassCompositor. We don't want to force such modules to pass
|
||||
# this arg so we default to something sane.
|
||||
my $orig_apply = $args{orig_apply} || Moose::Meta::Role->can('apply');
|
||||
$self->$orig_apply($role);
|
||||
|
||||
$self->role_generator->($parameters,
|
||||
operating_on => $role,
|
||||
consumer => $args{consumer},
|
||||
);
|
||||
|
||||
# don't just return $role here, because it might have been changed when
|
||||
# metaroles are applied
|
||||
return $MooseX::Role::Parameterized::CURRENT_METACLASS;
|
||||
}
|
||||
|
||||
sub _role_for_combination {
|
||||
my $self = shift;
|
||||
my $parameters = shift;
|
||||
|
||||
return $self->generate_role(
|
||||
parameters => $parameters,
|
||||
);
|
||||
}
|
||||
|
||||
around apply => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
my $consumer = shift;
|
||||
my %args = @_;
|
||||
|
||||
my $role = $self->generate_role(
|
||||
consumer => $consumer,
|
||||
parameters => \%args,
|
||||
orig_apply => $orig,
|
||||
);
|
||||
|
||||
$role->apply($consumer, %args);
|
||||
};
|
||||
|
||||
around reinitialize => sub {
|
||||
my $orig = shift;
|
||||
my $class = shift;
|
||||
my ($pkg) = @_;
|
||||
my $meta = blessed($pkg) ? $pkg : find_meta($pkg);
|
||||
|
||||
my $meta_meta = $meta->meta;
|
||||
|
||||
my %p;
|
||||
if ( $meta_meta->can('does_role') && $meta_meta->does_role(__PACKAGE__) ) {
|
||||
%p = map { $_ => $meta->$_ }
|
||||
qw( parameterized_role_metaclass parameters_class );
|
||||
$p{parameters_metaclass} = $meta->parameters_metaclass
|
||||
if $meta->_has_parameters_metaclass;
|
||||
$p{role_generator} = $meta->role_generator
|
||||
if $meta->has_role_generator;
|
||||
}
|
||||
|
||||
my $new = $class->$orig(
|
||||
@_,
|
||||
%p,
|
||||
);
|
||||
|
||||
return $new;
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
MooseX::Role::Parameterized::Meta::Trait::Parameterizable - trait for parameterizable roles
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.11
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is the trait that is applied to the metaclass for parameterizable roles,
|
||||
roles that have their parameters currently unbound. These are the roles that
|
||||
you use L<Moose/with>, but instead of composing the parameterizable role, we
|
||||
construct a new parameterized role
|
||||
(L<MooseX::Role::Parameterized::Meta::Role::Parameterized>) and use that new
|
||||
parameterized role instead.
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=head2 parameterized_role_metaclass
|
||||
|
||||
The name of the class that will be used to construct the parameterized role.
|
||||
|
||||
=head2 parameters_class
|
||||
|
||||
The name of the class that will be used to construct the parameters object.
|
||||
|
||||
=head2 parameters_metaclass
|
||||
|
||||
A metaclass representing this role's parameters. It will be an anonymous
|
||||
subclass of L</parameters_class>. Each call to
|
||||
L<MooseX::Role::Parameters/parameter> adds an attribute to this metaclass.
|
||||
|
||||
When this role is consumed, the parameters object will be instantiated using
|
||||
this metaclass.
|
||||
|
||||
=head2 role_generator
|
||||
|
||||
A code reference that is used to generate a role based on the parameters
|
||||
provided by the consumer. The user usually specifies it using the
|
||||
L<MooseX::Role::Parameterized/role> keyword.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 add_parameter $name, %options
|
||||
|
||||
Delegates to L<Moose::Meta::Class/add_attribute> on the
|
||||
L</parameters_metaclass> object.
|
||||
|
||||
=head2 construct_parameters %arguments
|
||||
|
||||
Creates a new L<MooseX::Role::Parameterized::Parameters> object using metaclass
|
||||
L</parameters_metaclass>.
|
||||
|
||||
The arguments are those specified by the consumer as parameter values.
|
||||
|
||||
=head2 generate_role %arguments
|
||||
|
||||
This method generates and returns a new instance of
|
||||
L</parameterized_role_metaclass>. It can take any combination of
|
||||
three named arguments:
|
||||
|
||||
=over 4
|
||||
|
||||
=item parameters
|
||||
|
||||
A hashref of parameters for the role, same as would be passed in at a "with"
|
||||
statement.
|
||||
|
||||
=item package
|
||||
|
||||
A package name that, if present, we will use for the generated role; if not,
|
||||
we generate an anonymous role.
|
||||
|
||||
=item consumer
|
||||
|
||||
=for stopwords metaobject
|
||||
|
||||
A consumer metaobject, if available.
|
||||
|
||||
=back
|
||||
|
||||
=head2 apply
|
||||
|
||||
Overrides L<Moose::Meta::Role/apply> to automatically generate the
|
||||
parameterized role.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Role-Parameterized>
|
||||
(or L<bug-MooseX-Role-Parameterized@rt.cpan.org|mailto:bug-MooseX-Role-Parameterized@rt.cpan.org>).
|
||||
|
||||
There is also a mailing list available for users of this distribution, at
|
||||
L<http://lists.perl.org/list/moose.html>.
|
||||
|
||||
There is also an irc channel available for users of this distribution, at
|
||||
L<C<#moose> on C<irc.perl.org>|irc://irc.perl.org/#moose>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shawn M Moore <code@sartak.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
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.
|
||||
|
||||
=cut
|
||||
101
database/perl/vendor/lib/MooseX/Role/Parameterized/Meta/Trait/Parameterized.pm
vendored
Normal file
101
database/perl/vendor/lib/MooseX/Role/Parameterized/Meta/Trait/Parameterized.pm
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
package MooseX::Role::Parameterized::Meta::Trait::Parameterized;
|
||||
# ABSTRACT: trait for parameterized roles
|
||||
|
||||
our $VERSION = '1.11';
|
||||
|
||||
use Moose::Role;
|
||||
use MooseX::Role::Parameterized::Parameters;
|
||||
use Moose::Util 'find_meta';
|
||||
use namespace::autoclean;
|
||||
|
||||
has genitor => (
|
||||
is => 'ro',
|
||||
does => 'MooseX::Role::Parameterized::Meta::Trait::Parameterizable',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
has parameters => (
|
||||
is => 'rw',
|
||||
isa => 'MooseX::Role::Parameterized::Parameters',
|
||||
);
|
||||
|
||||
around reinitialize => sub {
|
||||
my $orig = shift;
|
||||
my $class = shift;
|
||||
my ($pkg) = @_;
|
||||
my $meta = blessed($pkg) ? $pkg : find_meta($pkg);
|
||||
|
||||
my $genitor = $meta->genitor;
|
||||
my $parameters = $meta->parameters;
|
||||
|
||||
my $new = $class->$orig(
|
||||
@_,
|
||||
(defined($genitor) ? (genitor => $genitor) : ()),
|
||||
(defined($parameters) ? (parameters => $parameters) : ()),
|
||||
);
|
||||
# in case the role metaclass was reinitialized
|
||||
$MooseX::Role::Parameterized::CURRENT_METACLASS = $new;
|
||||
return $new;
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
MooseX::Role::Parameterized::Meta::Trait::Parameterized - trait for parameterized roles
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.11
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is the trait for parameterized roles; that is, parameterizable roles with
|
||||
their parameters bound. All this actually provides is a place to store the
|
||||
L<MooseX::Role::Parameterized::Parameters> object as well as the
|
||||
L<MooseX::Role::Parameterized::Meta::Role::Parameterizable> object that
|
||||
generated this role object.
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=for stopwords genitor metaobject
|
||||
|
||||
=head2 genitor
|
||||
|
||||
Returns the L<MooseX::Role::Parameterized::Meta::Role::Parameterizable>
|
||||
metaobject that generated this role.
|
||||
|
||||
=head2 parameters
|
||||
|
||||
Returns the L<MooseX::Role::Parameterized::Parameters> object that represents
|
||||
the specific parameter values for this parameterized role.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Role-Parameterized>
|
||||
(or L<bug-MooseX-Role-Parameterized@rt.cpan.org|mailto:bug-MooseX-Role-Parameterized@rt.cpan.org>).
|
||||
|
||||
There is also a mailing list available for users of this distribution, at
|
||||
L<http://lists.perl.org/list/moose.html>.
|
||||
|
||||
There is also an irc channel available for users of this distribution, at
|
||||
L<C<#moose> on C<irc.perl.org>|irc://irc.perl.org/#moose>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shawn M Moore <code@sartak.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
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.
|
||||
|
||||
=cut
|
||||
60
database/perl/vendor/lib/MooseX/Role/Parameterized/Parameters.pm
vendored
Normal file
60
database/perl/vendor/lib/MooseX/Role/Parameterized/Parameters.pm
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package MooseX::Role::Parameterized::Parameters;
|
||||
# ABSTRACT: base class for parameters
|
||||
|
||||
our $VERSION = '1.11';
|
||||
|
||||
use Moose;
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
no Moose;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
MooseX::Role::Parameterized::Parameters - base class for parameters
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.11
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is the base class for parameter objects. Currently empty, but I reserve
|
||||
the right to add things here.
|
||||
|
||||
Each parameterizable role gets their own anonymous subclass of this;
|
||||
L<MooseX::Role::Parameterized/parameter> actually operates on these anonymous
|
||||
subclasses.
|
||||
|
||||
Each parameterized role gets their own instance of the anonymous subclass
|
||||
(owned by the parameterizable role).
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Role-Parameterized>
|
||||
(or L<bug-MooseX-Role-Parameterized@rt.cpan.org|mailto:bug-MooseX-Role-Parameterized@rt.cpan.org>).
|
||||
|
||||
There is also a mailing list available for users of this distribution, at
|
||||
L<http://lists.perl.org/list/moose.html>.
|
||||
|
||||
There is also an irc channel available for users of this distribution, at
|
||||
L<C<#moose> on C<irc.perl.org>|irc://irc.perl.org/#moose>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shawn M Moore <code@sartak.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
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.
|
||||
|
||||
=cut
|
||||
248
database/perl/vendor/lib/MooseX/Role/Parameterized/Tutorial.pod
vendored
Normal file
248
database/perl/vendor/lib/MooseX/Role/Parameterized/Tutorial.pod
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
# PODNAME: MooseX::Role::Parameterized::Tutorial
|
||||
# ABSTRACT: why and how
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
MooseX::Role::Parameterized::Tutorial - why and how
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.11
|
||||
|
||||
=head1 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
|
||||
L<Moose::Cookbook::Roles::Comparable_CodeReuse> for an introduction to L<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 C<-alias>
|
||||
for renaming methods and C<-excludes> for ignoring methods. These options are
|
||||
primarily for resolving role conflicts. Depending on how much of a purist you are,
|
||||
these options are I<solely> for resolving role conflicts. See
|
||||
L<Moose::Cookbook::Roles::Restartable_AdvancedComposition> for more about C<-alias> and C<-excludes>.
|
||||
|
||||
Because roles serve many different masters, they usually provide only the least
|
||||
common denominator of functionality. To empower roles further, more
|
||||
configurability than C<-alias> and C<-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 C<url> attribute.
|
||||
|
||||
Parameterized roles offer a solution to these (and other) kinds of problems.
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
=head2 C<with>
|
||||
|
||||
The syntax of a class consuming a parameterized role has not changed
|
||||
from the standard C<with>. You pass in parameters just like you
|
||||
pass in C<-alias> and C<-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 L<Data::OptList> to make sure that a list of role
|
||||
names and associated parameters is handled correctly.
|
||||
|
||||
=head2 C<parameter>
|
||||
|
||||
Inside your parameterized role, you specify a set of parameters. This is
|
||||
exactly like specifying the attributes of a class. Instead of L<Moose/has> you
|
||||
use the keyword C<parameter>, but your parameters can use any options to
|
||||
C<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 C<has> is that we create a reader accessor for you by
|
||||
default. In other words, we assume C<< 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 L<Moose/has>. If you do not want an accessor, you can use
|
||||
C<< is => 'bare' >>.
|
||||
|
||||
=head2 C<role>
|
||||
|
||||
C<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 C<role> is an object containing the parameters specified by
|
||||
C<with>. You can access the parameters just like regular attributes on that
|
||||
object.
|
||||
|
||||
Each time you compose this parameterized role, the C<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
|
||||
C<< method name => sub { ... } >> instead of the usual C<sub name { ... }>.
|
||||
Your methods may, of course, close over the parameter object. This means that
|
||||
your methods may use parameters however they wish!
|
||||
|
||||
=head1 USES
|
||||
|
||||
Ideally these will become fully-explained examples in something resembling
|
||||
L<Moose::Cookbook>. But for now, only a brain dump.
|
||||
|
||||
=over 4
|
||||
|
||||
=item 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<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,
|
||||
...
|
||||
);
|
||||
};
|
||||
|
||||
=item 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 { ... };
|
||||
};
|
||||
|
||||
=item 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) { ... }
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
=item Deciding a backend
|
||||
|
||||
Your role may be able to freeze and thaw your instances using L<YAML>, L<JSON>,
|
||||
L<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;
|
||||
}
|
||||
...
|
||||
};
|
||||
|
||||
=item 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";
|
||||
|
||||
...
|
||||
};
|
||||
|
||||
=back
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Role-Parameterized>
|
||||
(or L<bug-MooseX-Role-Parameterized@rt.cpan.org|mailto:bug-MooseX-Role-Parameterized@rt.cpan.org>).
|
||||
|
||||
There is also a mailing list available for users of this distribution, at
|
||||
L<http://lists.perl.org/list/moose.html>.
|
||||
|
||||
There is also an irc channel available for users of this distribution, at
|
||||
L<C<#moose> on C<irc.perl.org>|irc://irc.perl.org/#moose>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shawn M Moore <code@sartak.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
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.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user