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



    http://blogs.perl.org/users/byterock/2018/11/moose-loose-ends-v.html

 

© Lightnetics 2018