Moose Loose Ends V

Still make errors pretty day here in the Moose-Pen.
Yesterday I re-discovered that I had 'MooseX::Constructor::AllErrors' set up in my code. I was even using it to test fail conditions like this test;


$in_hash = {
view => {
name => undef,
alias => undef
}
};
eval {
$da = Database::Accessor->new($in_hash);
};
ok( $@->has_errors(), "Error on New" );
ok( scalar( $@->errors ) == 2, "Two errors on new" );
...

in test case '30_view.t'

This MooseX gathers up all Constructor errors and puts them in a nice 'error-class' and then returns that class with the '$@'. So all along I was getting the that you can play with. It even clasifies the errors for you into 3 attributes


  • missing

    • lists all 'required' elements that are missing;

  • invalid

    • lists any type or coecion errors and;

  • misc

    • any other errors no listed above.


Now this is all nice and good as my end users get a object they can work with but I still want to make it easer for them. but and I think I can work with this to fix up the error messages a little. I will have to put into my documentation that the end user can use that if they want to capture these errors themselves.
Now for today’s mission make my errors a little more friendly. Moose actually helps me out here and I am going to try and take advantage of the 'around BUILDARGS' to change my error message;

As it stands now I have just this;


around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my $ops = shift(@_);
if ( $ops->{retrieve_only} ) {
$ops->{no_create} = 1;
$ops->{no_retrieve} = 0;
$ops->{no_update} = 1;
$ops->{no_delete} = 1;
}
return $class->$orig($ops);
};

Very standard stuff right out of the Moose::Cookbook. Now a few quick changes to this patten to get me off that well worn track;

...
$ops->{no_delete} = 1;
}
-- return $class->$orig($ops);
++ my $instance;
++ eval{ $instance = $class->$orig($ops)};
++ if ($@){
++ return $@;
++ }
++ else {
++ return $instance;
++ }
};

First time I have ever tried to use sometng other that that standard return but I see no reson why it should work ok. I need only give my '30_view.t' test a whirl to see if this works;

ok 1 - DA View is correct
ok 2 - DAS View is correct
ok 3 - Cannot access attribute directly
ok 4 - Cannot change attribute directly
ok 5 - View is Required
not ok 6 - Got error Constructor object

and the last fail was

Can't locate object method "has_errors" via package "Moose::Exception::ValidationFailedForInlineTypeConstraint" at 30_view.t line 103.

so not 100% right yet as I am not getting a 'AllError' class back so I had a quick peek below the hood I see what I was getting and it was a 'Moose::Exception::ValidationFailedForInlineTypeConstrain'. To fix this and get my my test to work again I tried this;

if ($@){
-- return $@;
++ die $@;
}
else {
return $instance;
}

as I want to die with my ''MooseX::Constructor::AllErrors' all I was getting before was the first error on the stack.

After that little change all my tests passed so far so good but I thing this test should be added;


like(
exception {$da = Database::Accessor->new({}); },
qr /Attribute \(elements\) is required/,
"Proper scalar error on empty build"
);

what I am checking for is that I have not changed how excelptions work when I do not wrap the 'new' call with an 'eval'. I am basically asking for the 'scalar' value of '$@'. On my test run I get

...
ok 10 - View: param alias fails
ok 11 - Proper scalar error on empty build

Looking good! Now to build an better error-message but that is a story for tomorrow.

moosefly.gif

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