Over Stuffed Moose

Sometimes being both newbie and a keener can be a dangerous combination. Well today I sort of fell into that trap.

Well I started doing the first refactoring of my Moose classes (not for AD&D this time this is some real world code) I was working with. So I wanted to move all the common bits into a single role then create a few 'base' classes that comsume that base roles and add some other sutff. Finally I was going to 'extend' these classes with some default values and then polish them by adding a few roles to customize the end product.

So like this

{
package Product::Base;
   use Moose::Role;
   . ..
}

{
package Product::Liquid;
   use Moose;
   with (qw(Product::Base)) ;
   ...
}
{
Package  Product::Liquid::Air
 use Moose;
extends  'Product::Liquid';
with (qw(Product::Hazmat::MDSD  Product::Meta::NPC Product::Hazmat::UN1001 ));
}

And things worked fine, the birds where singing and the sun was shining.

Well then I got keen.

In my 'Product::Hazmat::MDSD' I decided to add in a 'Requires' like this

package Product::Hazmat::MDSD;

use warnings;
use strict;
use Moose::Role;
requires  (qw(un_id barcode name product_meta ));#  )); 

To make sure any other programmer who came along after me would be able to use this Role. Well this is what I got;


 Load of  Product  failed:Air
   Error='Product::Meta::NPC|Product::Hazmat::UN1001|Product::Hazmat::MDSD' requires the methods 'un_id', 'barcode' and 'product_meta' to be implemented by 'Product::Liquid::Air' at /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/Moose/Exception.pm line 37
...

tumblr_lye4xaBEhZ1rn95k2o1_250.gif

Well I could of just taken that offending line out and be done with it but I just had to find out what was wrong. Well I know 'un_id' comes from my UN1001, while barcode and product_meta from NPC. What is this? It should just be the simple case of the end role consuming from the ones that have already been used. Well I guess not

Well after lots of moving of code about I did get it to work but is was Not what I wanted. I ended up adding the 'Product::Meta::NPC' and 'Product::Hazmat::UN1001' roles to the 'Product::Liquid' package like this

{
package Product::Liquid;
   use Moose;
   with (qw(Product::Base Product::Meta::NPC Product::Hazmat::UN1001 )) ;
   ...
}

but that defeats the purpose of extending that class to another that would have the properties of Liquid Air

So where did I go wrong??

Well it seem that a 'Requires' for a role is very very strict in is interpretation of this

'roles can also require that the consuming class define certain methods of its own'

little tid-bit from the POD. So the 'Class' must have the method not just a consume a role that has it. The second arrangement works because by the time I get to the my 'with' in 'Product::Liquid::Air' the role methods ( 'un_id', 'barcode' and 'product_meta' ) are already part of the class.

Seems I will have to do a little more work on this??

Again I feel a little like this guy!

moose.statue.sex.1.jpg

1 Comment

This is a known issue in Moose. There are TODO test cases for it all over the test suite. I believe Moo doesn't suffer from this problem.

You may be able to split your with in two to work around the issue:

{
   package Product::Liquid;
   use Moose;
   with qw(Product::Base);
   with qw(Product::Meta::NPC Product::Hazmat::UN1001);
}

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations