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)
============================================================*/

Reply via email to