Entering MooseX, Part the Sixth
Well in my last post I decided to use a hash-ref rather than an array-ref as a way to expand my little MooseX and let the user set have a set of required roles and or a set where only one role is required from a set.
I figured this made the API a little eirer to understand and even read inline.
Now how to implement this?
Well I start first with 'MooseX::Meta::Method::Role::Authorized' do this
has requires =>
( is => 'ro',
-- isa => 'ArrayRef',
++ isa => 'HashRef',
default => sub { [] } );
So just change the type, simple enough. Now I only have to change how the 'authorized_do' sub works as now I have to process a hash-ref rather than an array-ref.
Now I did notice that in the original code if you sent an empty array-ref to the sub it will throw this error
You must supply a role name to does() at C:\Dwimperl\perl\site\lib\Moose\Exception.pm line 37
...
It does take some reading to figure out what exactly you did wrong. While not a bad message I think I can improve on it in my code by throwing a more helpful message.
Now in my version I what I want to do is check to ensure that at least one of my two API keys are present and points to an array-ref, otherwise I will die with a suitable message.
Now it is always best IMHO to catch such things early on in the process and the earliest I could find was the 'around wrap' code found in the 'MooseX::Meta::Method::Role::Authorized;' class.
round wrap => sub {
my ($wrap, $method, $code, %options) = @_;
...
now with a little help from Data::Dumper I discovered that my hash-ref was to be found in the '%options' param of the above.
$VAR1 = {
'requires' => {
'requires'=>['Product::BRULE::COD'],
'one_of'=>['Product::BRULE::Standing_Offer','Product::BRULE::PO'],
},
'name' => 'bin_swap',
'package_name' => 'Product::Moves'
};
so I add in a quick check like this
round wrap => sub {
my ($wrap, $method, $code, %options) = @_;
die "requires hash-ref must have either a 'requires' or 'one_of' or both key that points to an array-ref of Roles!"
unless (((exists($requires->{requires}) and ref($requires->{requires}) eq 'ARRAY')) or
((exists($requires->{one_of}) and ref($requires->{one_of}) eq 'ARRAY')));
...
Any I get something like this;
requires hashref must have either a 'requires' or 'one_of' or both key to an array ref of Roles! at C:/Dwimperl/perl/site/lib/MooseX/Meta/Method/Role/Authorized.pm line 28.
Compilation failed in require at myorder.pl line 9.
BEGIN failed--compilation aborted at myorder.pl line 9.
I could spill back the entered values but the person calling this would already know what they are and for this low of an API it would be overkill. I am also referring to the internal 'requires' which may cause some confusion so I will have to change that. Now I do have the class and sub name handy so I should throw that in as well and after a little edit I get
Product::Moves bin_swap authorized_roles declarator hash-ref must have either one or both keys 'requires' and 'one_of' and they must point to an array ref of Roles! at C:/Dwimperl/perl/site/lib/MooseX/Meta/Method/Role/Authorized.pm line 28.
Compilation failed in require at myorder.pl line 9.
BEGIN failed--compilation aborted at myorder.pl line 9.
Much nicer.
Now some may balk at me using the 'unless' as it doesn't have the 'Conway' seal of approval (or is that camel??) but I like it here as it clearly means to me that if my hash-ref doesn't have a 'requires' key that points to an array-ref or an 'one_of' key that points to an array-ref something is wrong.
Now the next is to process this incoming hash but I think I will leave that till tomorrow.
Hopefully no one will accuse me of milking this for posts
here
. Now one get
Leave a comment