Moose Loose Ends Part the Seventh
Its very bad form day here in the Moose-pen
Today I wanted to clean up one thing on construction error handling namely getting the correct number of errors back on my 'AllErrors' object.
First a little house cleaning. The first thing I did today was create a new sub called '_new_misc_error'
sub _new_misc_error {
my $self = shift;
my ($error,$line,$filename) = @_;
my $misc = MooseX::Constructor::AllErrors::Error::Misc->new({message =>"Database::Accessor New Error: "
. $error->message
. " at Line "
. $line
. " file: "
. $filename});
return $misc;
}
as I didn't wand to duplicate the above code because I have both 'missing' and 'invalid' errors to convert to Misc errors.
The 'eval' code block now looks like this;
eval{ $instance = $class->$orig($ops)};
if ($@) {
my @errors;
foreach my $error ($@->missing()){
push(@errors, $class->_new_misc_error($error,$line,$filename));
}
foreach my $error ($@->invalid()){
push(@errors, $class->_new_misc_error($error,$line,$filename));
}
$@->add_error(@errors);
die $@;
}
By the way you have to be careful here and watch your calling signature closely when working in the 'around' block. I am calling that new subroutine with the '$class' and not the '$orig' get that mixed up there you in for all sorts of 'Moose-Poop' or worse!
The above works fine and dandy but I still get extra errors that cause my test to fail;
...
ok 7 - Error on New
not ok 8 - Two errors on new
ok 9 - Proper scalar error on empty build
…
I just could account for this in my test and make a note in my POD that the error counts are always doubled. Now you know why the title for today post is 'bad form day'. It is never a good idea to give unexpected results in your code even if you document them.
I could see some smarty pants using the scalar value of the 'AllErrors::errors' attribute in some sort of test system that spews out an email to some 'Pointy Haired Boss' that says there are '4' errors in the system today. Well programmer 'Q' goes in and fixes both bugs and she duly logs '2' bugs fixed. At 02:37 the 'Pointy Haired Boss' is all upset because the release when out with '4' bugs reported and only '2' are reported as fixed. So you programmer is awoken from her slumber to explain that is how it works etc etc. Anyway you get the point.
So quick fix for the above;
}
++ $@->{errors} = undef;
$@->add_error(@errors);
Time for this I think;
The above does work but it has to be the very high up on the bad-form list. It does remove the two bugs present and my tests passes at least for the error count. It is just so perl 5.0 a hack at worst a kludge at best and goodness know what sort of impact this may have. So that is right out.
For once I actually read the manual (not something a middle aged man does often) and I found an easy solution to my error count problem, just send back a new 'AllErrors' object;
…
-- $@->add_error(@errors);
++ my $all = MooseX::Constructor::AllErrors::Error::Constructor->new(
++ caller => [ caller( Class::MOP::class_of($class)->is_immutable ? 2 : 4) ],
++ );
++ $all->add_error(@errors);
-- die $@;
++ die $all;#$error; #$@;
++ }
and when I run my tests as I expected I get this error
Can't locate object method "attribute" via package "MooseX::Constructor::AllErrors::Error::Misc"
as I simply invalided tests two tests;
ok( $errors[0]->attribute->name() == 'name', "View: param name fails" );
ok( $errors[1]->attribute->name() == 'alias', "View: param alias fails" );
as they are no longer 'MooseX::Constructor::AllErrors::Error::Required' as expected by my test but are 'Misc'. At lease my counts are correct;
...
ok 8 - Two errors on new
not ok 9 - View: param name fails
not ok 10 - View: param alias fails
…
Now I have another problem. There might be some smarty pants out there who might want to leverage the 'name' attribute on the MooseX::Constructor::AllErrors::Error::Required class for some reason or another. With only the “Misc” error they can't and they will be forced to parse that out of the 'message' attribute, again bad form. Promise something 'AllErrors' and then do not deliver.
What to do?
The simple solution provide two possible paths for the end user.
- Separate errors or
- one consolidate error
Well I guess I have my post for tomorrow.
Leave a comment