2011-03-06 7 views
5

Estoy convirtiendo una aplicación heredada para usar Moose (y Catalyst) y tengo la siguiente pregunta.Perl Moose - compruebe si la variable es un tipo de datos Moose

¿Cómo determino el tipo de alce de entrada de Moose por un usuario?

A continuación, crudo, ejemplo I 'enviar' múltiples consultas y validar los datos contra los campos de formulario esperados 'id', 'nombre' y 'correo electrónico' utilizando el método 'validar' muy básico a continuación.

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' => '[email protected]' 
       }, 
       { '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" } 
       }; 
    } 
} 

Para probar este código sólo tiene que ejecutar ...

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

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

1; 

¿Es posible hacer algo como esto en el que una variable de configuración con ISA pone a 'Cualquier' ...

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

... luego prueba para tipos específicos de la siguiente manera?

$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'; 

gracias de antemano

EDITAR: @bvr - gracias por tomarse el tiempo para responder, soy relativamente nuevo en los alces por lo que su uso de MooseX :: Parámetros :: Validar podría bien sea la solución final, aunque no exactamente lo que estoy buscando. Mi intención es poder informar cada campo específico que está en error en lugar de informar una falla de validación como un todo. Para ese fin, pensé que podría definir un soporte de entrada predeterminado compatible con Moose con isa establecido en 'Any'. Luego 'eval' (o algo así) para ver si los datos se ajustan a un tipo particular (Int, Str o algún tipo personalizado definido por mí).

Lo que intentaba hacer con la referencia "$ self-> validate_field-> meta-> isa ('Int') ..." era algo similar a una unión en C/C++ donde una variable puede ser de diferentes tipos; en este caso, solo intento probar si los datos se ajustan a un cierto tipo de datos.

Respuesta

2

No estoy seguro de haber seguido bastante la última parte de su pregunta, pero su ejemplo inicial podría beneficiarse del uso de MooseX::Params::Validate.

Editar: He hecho algunos códigos para evaluar mi sugerencia.

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' => '[email protected]' 
      }, 
      { '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(); 

Otro enfoque que puedo ver es hacer una clase Moose para datos (validación incluyó esta manera) y comprobar si la instancia se puede crear sin error de validación. Algo como esto:

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 => '[email protected]'}, 
    { 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"; 
    }; 
} 
+0

gracias por tomarse el tiempo para responder, soy relativamente nuevo en los alces por lo que su uso de MooseX :: Parámetros :: Validar bien podría ser la solución final, sin embargo no es lo que soy buscando. – user647248

+0

@ user647248 - dos notas aquí. Primero, puede inspeccionar la excepción para descubrir qué validación de campo falló. En segundo lugar, la técnica descrita con 'MooseX :: Params :: Validate' se puede modificar bastante fácilmente para verificar los valores individualmente. – bvr

+0

+1 Buena manera de probar proyectos con tipos personalizados. –

Cuestiones relacionadas