(Apologies if this is a dupe; I've tried sending this a few times today and
have been experiencing issues with my msmtp configs.)


tl;dr version: no questions here, just some discoveries that I wanted to
spread a little farther and get google-indexed :)


A while back I posted on Stack Overflow about extracting the metaclass from
inside a role definition:

http://stackoverflow.com/questions/1758884/how-can-i-access-the-meta-class-of-the-module-my-moose-role-is-being-applied-to

... which lead me to MooseX::Role::Parameterized (a continued two big
thumbs up BTW), which lead me to a few discoveries that I wanted to mention
here for posterity:

1. $args{consumer} only contains the metaclass of the target class at the
first level of parameterization. If the parameterized role (Role::A) is further
including another parameterized role (Role::B), then $args{consumer} in
Role::B will actually contain the metaclass of the first parameterized role
(MooseX::Role::Parameterized::Meta::Role::Parameterized), rather than
(a possible subclass of) Moose::Meta::Class.

In my application I'm nesting parameterized roles a few levels deep (the
code is cleaner this way rather than having lots of nested if statements),
so I've added a 'meta' parameter to the list of params being passed around:

# when calling the sub-role:
role {
    # isa Moose::Meta::Class
    my $meta = $args{consumer};

    with Role::B => {
        # other parameters...
        metaclass => $meta,
    };
};

# and in the subrole:
parameter metaclass => (
    is => 'ro', isa => 'Moose::Meta::Class',
    required => 1,
);

role {
    # isa Moose::Meta::Class
    my $meta = $params->metaclass;

    # isa Moose::Object
    my $consumer = $meta->name;
};



2. $args{consumer} won't even be a metaclass in the case of a role
application to a specific object instance -- in this case it will be the
type of the object being applied to.

role {
    my $meta = $args{consumer};
    $meta = $meta->meta if not $meta->isa('Moose::Meta::Class');

    # isa Moose::Object
    my $consumer = $meta->name;
};


Neither of these discoveries seemed obvious at first, so I wanted to pass
it on to save others some heartache.

I wonder if it might be useful to offer an API to extract the metaclass, as
the code above has essentially become boilerplate for all my parameterized
roles..


PS. Earlier today I was about to post here asking how one could apply a
parameterized role to an object instance (as there was no example in the
documentation), but in stepping through the Moose guts I discovered that
indeed it is just as simple as for non-parameterized roles:

my $foo = My::Foo->new();
Moose::Util::apply_all_roles($foo, My::Role, { parameter => 'value' });


Reply via email to