参考一个重载bool的对象死掉

时间:2016-08-23 17:40:15

标签: perl

我使用Data::FormValidator来处理DBIx :: Class中的一些数据验证(通过DBIx::Class::Validation)。 DBIC ::如果验证失败,验证最终会croak $results,其中$resultsData::FormValidator::Results对象。不幸的是,这个croak不会触发我在DBIC调用中的try / catch。

挖掘一下,我做了这个简化的测试用例(完全不包括DBIC):

use strict;
use Data::FormValidator;                                                                                                                                                                                                                       
use TryCatch; #or Try::Tiny or eval, same results for each

#setup a profile and values that fail under that profile
my $input_profile = {                                                                                                                                                                                                                          
   required => [ qw( good_ip bad_ip ) ],                                                                                                                                                                                           
   constraints => {                                                                                                                                                                                                                
     good_ip => 'ip_address',                                                                                                                                                                                                    
     bad_ip => 'ip_address',                                                                                                                                                                                                     
   }                                                                                                                                                                                                                               
};                                                                                                                                                                                                                         

my $validator = new Data::FormValidator({default => $input_profile});                                                                                                                                                                          

my $input_hashref = {                                                                                                                                                                                                                          
   'good_ip' => '127.0.0.1',                                                                                                                                                                                                                   
   'bad_ip'  => '300.23.1.1',                                                                                                                                                                                                                  
                    };
try {                                                                                                                                                                                                                                          
    my $results = $validator->check($input_hashref,'default');                                                                                                                                                                                 
    die $results;                                                                                                                                                                                                                              
} catch (Data::FormValidator::Results $e) {                                                                                                                                                                                                    
    print STDERR "failed with ".scalar(@{$e->invalid('bad_ip')})." invalid\n";                                                                                                                                                                 
}    

我希望我的catch块会被触发。相反,没有任何事情发生(继续执行)。

查看Results对象的来源,我发现它使用bool方法重载了success。删除它可以解决我的问题,但我不明白为什么。如果这是整个问题,有没有一种解决它的好方法?

1 个答案:

答案 0 :(得分:4)

TL; DR

这是TryCatch中的一个错误。 $results字符串化为空字符串,TryCatch调用if $@时应调用if defined $@

这是一个没有Data :: FormValidator的例子:

use strict;
use warnings 'all';
use 5.010;

package Foo;

use overload '""' => sub { '' };

sub new {
    bless {}, $_[0];
}

package main;

use TryCatch;

try {
    my $foo = Foo->new;
    die $foo;
}
catch($e) {
    say "<<<$e>>>";
}

当Perl词法分析器遇到某些关键字时,TryCatch使用Devel::Declare注入自定义代码。在这种情况下,它会生成如下内容: *

try;
{
    local $@;
    eval {
        my $foo = Foo->new;
        die $foo;
    };
    $TryCatch::Error = $@;
}

if ($TryCatch::Error) {

由于$@是空字符串,if ($TryCatch::Error)为false,永远不会输入catch块。

这是一个错误(TryCatch的many之一)。请改用eval或Try :: Tiny(只记得检查defined,而不是真实/虚假)。

*如果您想确切了解注入的内容,请将环境变量TRYCATCH_DEBUG设置为1。