It looks like MooseX :: Role :: Parameterized will do the trick:
Ordinary roles may require its consumers to have a specific list of method names. Since parameterized roles have direct access to your consumer, you can check it and throw errors if the consumer does not meet your needs. (link)
Role specialization details are retained from the extended class; he doesnβt even need to pass any parameters, all he needs to know is which parameters (list of fields to wrap) go to the role. The only clue is that the role should be used after the corresponding attributes have been defined in the class.
Therefore, the consumed class and role are defined as follows:
package My::Foo; use Moose; my @fields = qw(attr1 attr2); has \@fields => ( is => 'rw',
Addition . I found that if the parameterized role uses a different parameterized role, then $target_meta in the nested role will actually be a meta class of the parent role (isa MooseX::Role::Parameterized::Meta::Role::Parameterized ), and not a metaclass of the consuming class (isa Moose::Meta::Class ). To get the proper metaclass, you need to explicitly pass it as a parameter. I added this to all parameterized roles as a "best practice" template:
package MyApp::Role::SomeRole; use MooseX::Role::Parameterized;
Appendix 2 . I also found that if the role is applied to the instance of the object, and not to the class, then $target_meta in the role will actually be the class of the object making consumption:
package main; use My::Foo; use Moose::Util; my $foo = My::Foo->new; Moose::Util::apply_all_roles($foo, MyApp::Role::SomeRole, { parameter => 'value' }); package MyApp::Role::SomeRole; use MooseX::Role::Parameterized;
Therefore, this code is required when retrieving a metaclass at the beginning of a parameterized role:
role { my $params = shift; my %args = @_;
Ether
source share