Still Cleaning Moose
Still in mop up mode here in the Moose-Pen
I finally found a way (well not a good one) to generate an even better error message to my end users. You are of course quite familiar with this type of message;
Database::Accessor add_condition Error:
The following Attribute is required: (Element->name)
With constructor hash:
{
'operator' => '=',
'left' => {
'view' => 'People',
'name' => 'last_name'
},
'right' => {
'left' => {
'name' => 'salary'
},
'right' => {
'expressionx' => '*'
},
'function' => 'LEFT'
},
'close_parentheses' => 0,
'condition' => 'AND',
'open_parentheses' => 1
}
Very hard to find out that it is the 'expressionx' that is giving us grief. With the changes I have just completed I now get
The following Attribute is required: (Element->name)
Possiable missing/invalid key in or near:
{
'expressionx' => '*'
}
With constructor hash:
{
…
which leads me right to the right spot. Now for the explication of shame;
I had to resort to using another global var to get this to work. Not something I like to do.
To start I added it in at the top of the “Types” class
package Database::Accessor::Types;
our $NEW;
++our $LAST;
then way down in the '_element_coerce' sub I set it to the incoming '$hash'
sub _element_coerce {
my ($hash) = @_;
my $object;
++ $LAST=$hash;
now the if testaments that follow the above;
if ( exists( $hash->{expression} ) ) {
$hash->{expression} = uc( $hash->{expression} );
$object = Database::Accessor::Expression->new( %{$hash} );
}
elsif ( exists( $hash->{function} ) ) {
$hash->{function} = uc( $hash->{function} );
$object = Database::Accessor::Function->new( %{$hash} );
}
elsif ( exists( $hash->{value} ) || exists( $hash->{param} ) ) {
$object = Database::Accessor::Param->new( %{$hash} );
}
elsif ( exists( $hash->{ifs} ) ) {
die "Attribute (ifs) does not pass the type constraint because:
Validation failed for 'ArrayRefofThens' with less than 2 ifs"
if ( exists( $hash->{ifs} )
and ref( $hash->{ifs} ) eq 'ARRAY'
and scalar( @{ $hash->{ifs} } < 2 ) );
$object = Database::Accessor::If->new( %{$hash} );
}
else {
++ if (exists($hash->{left}) or exists($hash->{right})){
++ my %copy = %{Clone::clone($hash)};
++ delete($copy{left});
++ delete($copy{right});
++ $LAST=\%copy;
++ }
$object = Database::Accessor::Element->new( %{$hash} );
}
++ $LAST= undef;
return $object;
Will always either end in a success or fall though to the last 'else' where if the left or right keys exists I know I am in an error condition. I fist Clone the ref into a new Hash. This is done so I will get the correct 'constructor' hash on my error message, otherwise when I delete those two keys, they will be missing in that 'constructor' hash. I found that the really are just taking up space and without them the message reads much better. Finally I set my $LAST to a ref of the cloned %copy and then just let the 'Element->new' fail.
I also had to make a change to my '' sub in the 'AllErrors;' role as well by adding in a little flag
$error_package = $missing->attribute->definition_context->{package};
to capture the 'package' of the error. I then use that a little later on in this block;
++ my $on ="";
++ if ($error_package eq "Database::Accessor::Element"){
++ $on = " Possible missing/infalid key in or near:\n"
++ . Dumper($Database::Accessor::Types::LAST);
++ }
my $misc =
"Database::Accessor "
. $call
. " Error:\n"
. $error
++ . $on
. "With constructor hash:\n"
. Dumper($ops);
To check that I have an error in my 'Element' class and then put the location message in the $on var and then add that to the error message.
Well that is about it. I do not think I can squeeze any more out of the error capture. On to other things tomorrow.
Leave a comment