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.
Leave a comment