我正在将遗留应用程序转换为使用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 ++中的联合行变量可以是不同的类型 - 在这种情况下,我只是试图测试数据是否符合某种数据类型。
答案 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";
};
}