1 package MooseX::Role::Parameterized;
3 extends => { -as => 'moose_extends' },
4 around => { -as => 'moose_around' },
7 moose_extends 'Moose::Exporter';
11 use MooseX::Role::Parameterized::Meta::Role::Parameterizable;
13 our $CURRENT_METACLASS;
15 __PACKAGE__->setup_import_methods(
16 with_caller => ['parameter', 'role', 'method', 'has', 'with', 'extends',
17 'requires', 'excludes', 'augment', 'inner', 'before',
18 'after', 'around', 'super', 'override'],
19 as_is => [ 'confess', 'blessed' ],
25 confess "'parameter' may not be used inside of the role block"
26 if $CURRENT_METACLASS;
28 my $meta = Class::MOP::Class->initialize($caller);
31 $names = [$names] if !ref($names);
33 for my $name (@$names) {
34 $meta->add_parameter($name, @_);
40 my $role_generator = shift;
41 Class::MOP::Class->initialize($caller)->role_generator($role_generator);
47 return Moose::Role->init_meta(@_,
48 metaclass => 'MooseX::Role::Parameterized::Meta::Role::Parameterizable',
54 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
57 $names = [$names] if !ref($names);
59 for my $name (@$names) {
60 $meta->add_attribute($name, @_);
66 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
71 my $method = $meta->method_metaclass->wrap(
72 package_name => $caller,
77 $meta->add_method($name => $method);
82 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
87 Carp::croak "Roles do not currently support "
89 . " references for before method modifiers"
91 $meta->add_before_method_modifier($_, $code);
97 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
102 Carp::croak "Roles do not currently support "
104 . " references for after method modifiers"
106 $meta->add_after_method_modifier($_, $code);
112 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
117 Carp::croak "Roles do not currently support "
119 . " references for around method modifiers"
121 $meta->add_around_method_modifier($_, $code);
127 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
129 Moose::Util::apply_all_roles($meta, @_);
134 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
136 Carp::croak "Must specify at least one method" unless @_;
137 $meta->add_required_methods(@_);
142 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
144 Carp::croak "Must specify at least one role" unless @_;
145 $meta->add_excluded_roles(@_);
148 # see Moose.pm for discussion
150 return unless $Moose::SUPER_BODY;
151 $Moose::SUPER_BODY->(@Moose::SUPER_ARGS);
156 my $meta = $CURRENT_METACLASS || Class::MOP::Class->initialize($caller);
158 my ($name, $code) = @_;
159 $meta->add_override_method_modifier($name, $code);
162 sub extends { Carp::croak "Roles do not currently support 'extends'" }
164 sub inner { Carp::croak "Roles cannot support 'inner'" }
166 sub augment { Carp::croak "Roles cannot support 'augment'" }
174 MooseX::Role::Parameterized - parameterized roles
178 package MyRole::Counter;
179 use MooseX::Role::Parameterized;
197 method "increment_$name" => sub {
199 $self->$name($self->$name + 1);
202 method "decrement_$name" => sub {
204 $self->$name($self->$name - 1);
208 package MyGame::Tile;
211 with 'MyRole::Counter' => { name => 'stepped_on' };
213 =head1 L<MooseX::Role::Parameterized::Tutorial>
215 B<Stop!> If you're new here, please read
216 L<MooseX::Role::Parameterized::Tutorial>.
220 Your parameterized role consists of two things: parameter declarations and a
223 Parameters are declared using the L</parameter> keyword which very much
224 resembles L<Moose/has>. You can use any option that L<Moose/has> accepts. The
225 default value for the "is" option is "ro" as that's a very common case. These
226 parameters will get their values when the consuming class (or role) uses
227 L<Moose/with>. A parameter object will be constructed with these values, and
228 passed to the C<role> block.
230 The C<role> block then uses the usual L<Moose::Role> keywords to build up a
231 role. You can shift off the parameter object to inspect what the consuming
232 class provided as parameters. You can use the parameters to make your role
235 There are many paths to parameterized roles (hopefully with a consistent enough
236 API); I believe this to be the easiest and most flexible implementation.
237 Coincidentally, Pugs has a very similar design (I'm not yet convinced that that
242 You must use this syntax to declare methods in the role block:
243 C<< method NAME => sub { ... }; >>. This is due to a limitation in Perl. In
244 return though you can use parameters I<in your methods>!
246 L<Moose::Role/alias> and L<Moose::Role/excludes> are not yet supported. I'm
247 completely unsure of whether they should be handled by this module. Until we
248 figure out a plan, both declaring and providing a parameter named C<alias> or
249 C<excludes> is an error.
253 Shawn M Moore, C<< <sartak@bestpractical.com> >>
259 =item L<MooseX::Role::Matcher>
261 =item L<MooseX::Role::XMLRPC::Client>
263 =item L<MooseX::RelatedClassRoles>
265 =item L<WWW::Mechanize::TreeBuilder>
267 =item L<TAEB::Action::Role::Item>
269 =item L<KiokuDB::Role::Scan>
271 =item L<Fey::Role::MakesAliasObjects>
273 =item L<Fey::Role::HasAliasName>
275 =item L<Fey::Role::SetOperation>