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()){
$ALL_ERRORS->add_error($error);
}
};
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