So in working on adding real attributes to roles, I've come across another
thing I think needs fixing in Moose.
Basically, the way MetaRole currently works is sort of broken in regards
to roles, but mostly works merely by chance.
Specifically, when you use MetaRole to apply roles to a metaclass, you can
pass it either a Moose::Meta::Class or a Moose::Meta::Role, and it just
goes ahead and tries to apply all the roles you give it.
That means if you supply a "method_metaclass_roles" or
"attribute_metaclass_roles" option, MetaRole tries to apply these
regardless of whether the it got a class or role.
Even worse, when you provide a metaclass_roles option, it applies this
regardless of the type of thing it got.
This is especially problematic when it comes to the integration with
Moose::Exporter and MetaRole. You can create a module (like
MooseX::Aliases) that automatically tries to apply roles to anything that
loads it.
This has mostly worked so far because (meta-)roles & classes do share a
lot of methods. However, my work on adding real attributes to roles shows
this really breaking down.
The attributes in roles, while real objects, share almost no behavior with
attributes in classes. This means that when an attribute metarole is
applied, it will often try to wrap a method that doesn't even exist for a
role attribute.
To address all this, I've created a branch called
topic/metarole-distinguishes-role-meta. It includes all the changes from
topic/roles-have-real-attributes.
Basically, this branch changes MetaRole so that if you want to apply meta
roles to anything role-related, you have to be explicit about that. All
metaclass options for roles now start with "role_", so we have
"role_metaclass_roles", "role_attribute_metaclass_roles", and so on.
For existing MX modules, adopting this is pretty simple. If you _want_ to
apply a role to both class & role metaclasses, just pass two options:
apply_metaclass_roles(
metaclass_roles => [ 'Foo' ],
role_metaclass_roles => [ 'Foo' ],
attribute_metaclass_roles => [ 'Bar' ],
role_attribute_metaclass_roles => [ 'Bar' ],
);
Simple.
If you _don't_ want to apply a role to role metaclasses, you don't pass
the option.
I think this is necessary if we want to move forward with having real
attributes in roles. The alternative would be to force modules like
MX::Aliases to use a parameterized role (uber hack) or to somehow add
useless methods to Moose::Meta::Role::Attribute (uber hack).
Obviously, this will require some changes to MX modules, but probably not
too many, and I'm happy to work on that.
-dave
/*============================================================
http://VegGuide.org http://blog.urth.org
Your guide to all that's veg House Absolute(ly Pointless)
============================================================*/