Perl Moose - 检查变量是否为Moose数据类型

时间:2011-03-06 20:24:47

标签: perl moose

我正在将遗留应用程序转换为使用Moose(和Catalyst),并提出以下问题。

如何确定用户输入的Moose数据类型?

在下面的粗略示例中,我提交了多个查询,并使用下面非常基本的“验证”方法,根据预期的表单字段“id”,“name”和“email”验证数据。

use MooseX::Declare;
class CheckFields
{
    #has '_field' => ( is => 'rw', isa => 'Any' );

    # Fields on form and type to which they must match.
    method fields()
    {
        return [ { name => 'id',    type => 'Int' },
                 { name => 'name',  type => 'Str' },
                 { name => 'email', type => 'Email' }
               ];
    }

    # Dummy form posted requests.
    method queries()
    {
        return [ { 'id'    => 1,
                   'name'  => 'John Doe',
                   'email' => 'john@doe.net'
                 },
                 { 'id'    => 'John Doe',
                   'name'  => 1,
                   'email' => 'john.at.doe.net'
                 }
               ];
    }

    method validate_fields()
    {
        my $fields = $self->fields();

        # Loop through dummy form post requests
        foreach my $query ( @{ $self->queries } )
        {
            # Validate each field in posted form.
            foreach my $field ( @{ $fields } )
            {
                my $type = $field->{'type'};
                my $name = $field->{'name'};

                my $res = $self->validate->{ $type }( $query->{ $name} );
                print "$name is $res\n";
            }
            print "\n";
        }
    }

    # Very basic, slightly crude field validation.
    method validate()
    {
        return { 'Int'   => sub { my $val = shift; return $val =~ /^\d+$/ ? "ok" : "not ok" },
                 'Str'   => sub { my $val = shift; return $val =~ /^[a-zA-Z\s]+$/ ?"ok" : "not ok"  },
                 'Email' => sub { my $val = shift; return $val =~ /^(.+)\@(.+)$/ ?"ok" : "not ok"  }
               };
    }
}

要测试此代码,只需运行...

#!/usr/bin/perl
use Moose;
use CheckFields;

CheckFields->new()->validate_fields();

1;

是否可以执行以下操作:设置isa设置为'Any'的变量...

has '_validate_field' => ( is => 'rw', isa => 'Any' );

...然后测试具体类型如下?

$self->validate_field(1);
print $self->validate_field->meta->isa('Int') ? 'Int found' : 'Int not found';

$self->validate_field('ABC');
print $self->validate_field->meta->isa('Int') ? 'Int found' : 'Int not found';

提前谢谢

编辑:@bvr - 谢谢你花时间回复,我对Moose比较新,所以你使用MooseX :: Params :: Validate可能是最终的解决方案,但不是我正在寻找什么。我的目的是能够报告错误的每个特定字段,而不是整体报告验证失败。为此,我认为我可以定义一个默认的,Moose友好的输入持有者, isa 设置为'任何'。然后'eval'(或其他一些)来查看数据是否符合特定类型(Int,Str或我定义的某种自定义类型)。

我试图通过“$ self-> validate_field-> meta-> isa('Int')......”参考是C / C ++中的联合行变量可以是不同的类型 - 在这种情况下,我只是试图测试数据是否符合某种数据类型。

1 个答案:

答案 0 :(得分:2)

我不确定我是否完全按照您问题的最后一部分进行操作,但您最初的示例可能会因使用MooseX::Params::Validate而受益。

编辑:我制作了一些代码来评估我的建议。

use MooseX::Declare;
class CheckFields {

    use Moose::Util::TypeConstraints;
    use MooseX::Params::Validate;
    use Try::Tiny;
    use Data::Dump qw(pp);

    subtype 'Email' 
        => as 'Str' 
        => where {/^(.+)\@(.+)$/};

    method fields() {
        return [
            id    => {isa => 'Int'},
            name  => {isa => 'Str'},
            email => {isa => 'Email'},
        ];
    }

    method queries() {
        return [
            {   'id'    => 1,
                'name'  => 'John Doe',
                'email' => 'john@doe.net'
            },
            {   'id'    => 'John Doe',
                'name'  => 1,
                'email' => 'john.at.doe.net'
            }
        ];
    }

    method validate_fields() {
        my $fields = $self->fields();

        foreach my $query (@{$self->queries}) {
            try {
                my (%params) = validated_hash([%$query], @{$fields});
                warn pp($query) . " - OK\n";
            }
            catch {
                warn pp($query) . " - Failed\n";
            }
        }
    }
}

package main;

CheckFields->new()->validate_fields();

我可以看到的其他方法是为数据创建一个Moose类(以这种方式验证)并检查是否可以在没有验证错误的情况下创建实例。像这样:

use MooseX::Declare;
class Person {
    use Moose::Util::TypeConstraints;

    subtype 'Email'
        => as 'Str'
        => where {/^(.+)\@(.+)$/};

    has id    => (is => 'ro', isa => 'Int');
    has name  => (is => 'ro', isa => 'Str');
    has email => (is => 'ro', isa => 'Email');
}

package main;

use Try::Tiny;
use Data::Dump qw(pp);

my @tests = (
    { id => 1,          name => 'John Doe', email => 'john@doe.net'},
    { id => 'John Doe', name => 1,          email => 'john.at.doe.net'},
);

for my $query (@tests) {
    try {
        my $person = Person->new(%$query);
        warn pp($query) . " - OK\n";
    }
    catch {
        warn pp($query) . " - Failed\n";
    };
}