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