Moose Lights up

Is may be the end of the errors Day here in the Moose-Pen.

I spen quite a bit of time mulling over the various options and possible solutions to the rater large mess I made yesterday with my recursive call to a eval.

I did manage to do a very long coded version where de-factored my code back to what it was when I starter earlier this week. A block of code for each 'undef' sistuation.

I wasn’t really satisfied with that as it was ugly, unmaintainable and I think very fragile once I got into more that two levels of recursion on my evals.

What to do?

Well I had a peek at the guts of 'AllErrors' MooseX and from the I could see that it was warping anything I was doing a new with its own 'around BUILDARGS' so that explain why I was getting three errors rather than just one. I also means that I have to do another shameful act;

package Database::Accessor::Types;
our $NEW;
our $LAST;
# ABSTRACT: A Types Role for Database::Accessor:
use Moose::Role;
with qw(Database::Accessor::Roles::AllErrors);
++ our $ALL_ERRORS = MooseX::Constructor::AllErrors::Error::Constructor->new({caller=>[]});
Create yet another global variable. I figured if I had a variable out side the scope of any of the recursive evaluation I cold just load the errors in there as I went along. If you look at it a global error like this does not really matter much as if it is created I have a error and it will soon be gone and if there is no error I can just undef it when I no longer need it. To accomplish this I modified my '_create_instance' sub with a try catch;

sub _create_instance {
    my ( $class, $ops,$caller,$raw ) = @_;
    my $object;
    if ($NEW) {
    $LAST   = $ops;
        $object = $class->new( %{$ops} );
    else {
        try {
            $object = $class->new( %{$ops});
        } catch {
            foreach my $error ($_->errors()){
        if ($ALL_ERRORS->has_errors) {
            my ( $package, $filename, $line, $subroutine ) = caller($caller);   
            die _one_error($ALL_ERRORS, $ops, $subroutine, $package, $filename, $line,$subroutine, $NEW,$raw );
       $ALL_ERRORS =  undef;
So what I do in the above is take any errors that are trapped in the catch and move them into the global $ALL_ERRORS and then once through the 'catch' I simple check for 'has_errors' and then die with what ever returns from the '_one_error' call In the '_one_error' call the only change change I make was

--      die $die;
++      return $die;
and now when I do this;

 $da->add_condition( {
                leftx => {
                    name => 'last_name',
                    view => 'People'
                 operator => undef
I get this;

Database::Accessor Database::Accessor::add_condition Error:
The following Attribute is required: (conditions->left)
The following Attribute did  not pass validation: 
'conditions->operator' Constraint: The Operator 'undef', is not a valid Accessor Operator! Try one of '!=', '<', '<=', '<>', '=', '>', '>=', 'ALL', 'AND', 'ANY', 'BETWEEN', 'EXISTS', 'IN', 'IS NOT NULL', 'IS NULL', 'LIKE', 'NOT EXISTS', 'NOT IN', 'NOT LIKE', 'OR'
With constructor hash:
  'predicates' => {
                    'operator' => undef,
                    'leftx' => {
                                 'view' => 'People',
                                 'name' => 'last_name'
 at 42_new_validation.t line 93
very close to what I want; An when I run this

$da->add_condition( undef);
I get;

Database::Accessor Database::Accessor::add_condition Error:
You cannot add 'undef' with Database::Accessor::add_condition at 42_new_validation.t line 86
So not doing to bad with this one. I now only have to fix up this

$da = Database::Accessor->new({
    view => { name => 'People' },
    elements => [ { name => 'first_name', }, { name => 'last_name', }, ],
         conditions =>undef
as that is giving me bad results as well but at least I know why. I will have to make this little change;

      if ($@) {            
--          _one_error($@, $ops,'new',$package, $filename, $line, $subroutine,1);
++         die  _one_error($@, $ops,'new',$package, $filename, $line, $subroutine,1);
in my 'around BUILDARGS' and now I get;

Database::Accessor new Error:
The following Attribute did  not pass validation: 
'Roles::Common->conditions' Constraint: Validation failed for 'ArrayRefofConditions' with value undef
With constructor hash:
close enough for late at night.


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