[SP-pm] Data::Manager, alguém utiliza este troço ?!

Hernan Lopes hernanlopes at gmail.com
Tue Sep 3 21:15:34 PDT 2013


Eu prefiro deixar minhas validacoes juntos com as definicoes dos atributos
dos meus objetos, pois provavelmente eu vou validar um objeto antes de
fazer algo com ele.
Então eu faco o seguinte (o exemplo abaixo é para exemplificar atraves da
analise do mesmo, ele não irá compilar):

Em resumo:
1. defino os campos dentro de um hash, juntos com as validacoes
2. faco um loop para adicionar (com moose) cada campo na classe
3. defino um metodo salvar e esse metodo salvar vai verificar se o atributo
tem alguma validacao que deve ser executada

Entao eu termino com algo assim:

package My::Class;
use Moose;

#meta definicao dos meus atributos.. fica dentro de um hash... os atributos
ainda nao foram declarados
#nelas residem as validacoes, coerce, sql etc tudo que é simples e
relacionado a esse campo
#consigo incluir por exemplo um array com items para eu validar antes de
salvar, etc
#ex
my $attrs = {
    'preco' => {
        # isa => 'Int', #opcional
        req => 1,
        validation_regex => '(\d+)', # vou usar isso antes do metodo save
        coerce => sub { #   Vai executar tambem isso antes do save
            my ( $self, $value ) = @_;
            $value =~ s|^ +| +\$|g;
            $value =~ s|(.+)(,\|\.)00\$|$1|gi;
            $value =~ s|\D||gi;
            return $value;
        },
        sql =>
          {
            "type"       => "integer",
            "null_value" => 0
          },
        validacao_extra => [
          {
            rotulo => 'Verifica se contem numeros na mensagem',
            validacao => sub {
              my ( $campo ) = @_;
              return 1 if "valido" eq "valido";
              return 0;
            },
            msg_erro => "Tem erro nesse campo"
          }
          ,
          .... e depois adicionar o "validacao_extra" la ao final no
before_save
          ... e pronto...

        ]
    },
    'url' => {
        req              => 1,
        validation_regex => '^http',
        sql          => {
            type    => 'string',
            "index" => 'not_analyzed',
        }
    },

    'idade' => {
        req              => 1,
        validation_regex => '(\d+)',
        sql          => {
            "type"       => "integer",
            "null_value" => 0
        },
    },
};

# declara cada atributo para esta classe
foreach my $attr ( keys $attrs ) {
    #Mete o has dentro do foreach pra declarar cada chave dos meus $attrs
    has $attr => (
        is => 'rw', #podia vir do meu config la de cima ne...
        ( exists $attrs->{$attr}->{default} )
        ? (
            default => $attrs->{$attr}->{default}
          )
        : (),
    );
}

#coerce nos valores, é usado antes do metodo save... mas pode muito bem
usar o coerce do moo(u|se)
sub coerce {
    my ($self) = @_;
    foreach my $attr ( keys %$attrs ) {
        if ( exists $attrs->{$attr}->{coerce} && defined $self->$attr ) {
            $self->$attr(
                $attrs->{$attr}->{coerce}->( $self, $self->$attr ) );
        }
    }
}

#valida antes de salvar
#pode por exemplo verificar se foi setado e executar o $attrs->{ $attr }->{
validation_regex }, etc
sub validate {
    my ($self) = @_;
    foreach my $attr ( keys $attrs ) {
        return 0
          if exists $attrs->{$attr}->{req}
              and $attrs->{$attr}->{req} == 1
              and !defined $self->$attr;
         if ( exists $attrs->{ $attr }->{ validation_regex } ) {
            //valida a bagaca
            //pode ler de $self, ou receber o valor como parametro da sub
validate, etc
         }
    }
    return 1;
}

#before save...
before 'save' => sub {
    my ($self) = @_;
    $self->coerce();
};

#save somente se validate
sub save {
    my ($self) = @_;
    next unless $self->validate();
}



abs,

Hernan










2013/9/3 Blabos de Blebe <blabos at gmail.com>

> Na verdade foi até coincidência o Solli tocar no assunto, pq assim como
> mapas, eu ia perguntar isso pra vcs em breve.
>
>
> 2013/9/3 Blabos de Blebe <blabos at gmail.com>
>
>> > Blabos, e se você tiver 2 formulários na mesma página, por exemplo, um
>> de login e um de cadastro ? Vai ter que melhorar na gambi né ? heheheheheh
>>
>> Correto.
>>
>> > Se mudar o nome do campo entao… chora hehehe
>>
>> Correto denovo.
>>
>> > Marcar o campo errado em vermelho vai precisar de mais gambi :D
>>
>> Mais ou menos. Eu uso uma alternativa, no exemplo. Mas sim, é melhor
>> marcar o campo com vermelho.
>>
>> > Tem muitas vantagens usar o Data::Manager
>>
>> Correto denovo.
>>
>> O porém é que o meu exemplo é exatamente específico. Um form, quatro
>> campos.
>>
>> Não to dizendo que nao vou usar o Data::Manager, ou alguma solução
>> parecida. Só nao vou usar nessa semana :)
>>
>> As soluções apresentadas são apenas o mais pá-pow que dá pra fazer com
>> *a* hard-restriction desse sprint: tempo; e uma soft-restriction:
>> Data::Manager é novo pra mim.
>>
>> Depois eu refatoro. Tá previsto isso.
>>
>> Tá pronto x Tá bom.
>>
>> No meu caso nesse momento, tá pronto é mandatório. Quem me conhece sabe o
>> quanto eu gosto de gambiarra e o quanto tá custando esse tá pronto.
>>
>> :)
>>
>> []'s
>>
>>
>>
>>
>>
>> 2013/9/3 Lucas Oliveira <lucasmateus.oliveira at gmail.com>
>>
>>>
>>> Blabos, e se você tiver 2 formulários na mesma página, por exemplo, um
>>> de login e um de cadastro ? Vai ter que melhorar na gambi né ? heheheheheh
>>>
>>> Se mudar o nome do campo entao… chora hehehe
>>>
>>> Se precisar fazer um "pirulito" para importar para a base a validação
>>> não é aproveitável… esqueçe
>>>
>>> Marcar o campo errado em vermelho vai precisar de mais gambi :D
>>>
>>> Tem muitas vantagens usar o Data::Manager
>>>
>>>
>>> Em 03/09/2013, às 18:30, Blabos de Blebe <blabos at gmail.com> escreveu:
>>>
>>> Opa,
>>>
>>> O meu caso é muito simples (pequeno) e o meu tempo é curto. O que foi
>>> mais rápido pra mim foi essa tosqueria aqui:
>>>
>>> No controller:
>>>
>>> ...
>>> my $errors  = [];
>>>
>>> ## not null
>>> foreach my $field ( keys %{$fields} ) {
>>>     push @{$errors}, 'empty_' . $field
>>>       unless $fields->{$field};
>>> }
>>>
>>> ## unique
>>> foreach my $field (qw{ username email }) {
>>>     push @{$errors}, 'already_' . $field
>>>       if $rs_user->find( { $field => $fields->{$field} } );
>>> }
>>>
>>> ## invalid email
>>> push @{$errors}, 'invalid_email'
>>>   unless Email::Valid->address( $fields->{email} );
>>>
>>> if ( @{$errors} > 0 ) {
>>>     $c->stash->{user}   = $fields;
>>>     $c->stash->{errors} = $errors;
>>>     return;
>>> }
>>> ...
>>>
>>> No template:
>>>
>>>     [% IF errors.size > 0 %]
>>>         <div data-alert class="alert-box alert">
>>>             [% FOREACH error IN errors %]
>>>                 [% msg_block = 'msg_' _ error %]
>>>                 [% PROCESS $msg_block %]<br>
>>>             [% END %]
>>>             <a href="#" class="close">×</a>
>>>         </div>
>>>     [% END %]
>>> ...
>>>
>>> [% BLOCK msg_empty_full_name %]
>>>     Você precisa preencher o seu nome completo.
>>> [% END %]
>>>
>>> [% BLOCK msg_empty_username %]
>>>     Você precisa preencher o seu username.
>>> [% END %]
>>> ...
>>>
>>>
>>>
>>> Deve ter formas mais inteligentes de fazer isso, mas no momento, a mais
>>> inteligente pra mim, é a que eu consigo fazer mais rápido. Esse é meu
>>> "único" form.
>>>
>>> []'s
>>>
>>>
>>> 2013/9/3 Solli Honorio <shonorio at gmail.com>
>>>
>>>> Blabos, o que você está imaginando para validar ? Estilo old-school com
>>>> um encadeamento de if ? Dispatch table ? NDA ?
>>>>
>>>> Abraços,
>>>>
>>>> Solli Honorio
>>>>
>>>>
>>>> Em 3 de setembro de 2013 16:35, Blabos de Blebe <blabos at gmail.com>escreveu:
>>>>
>>>> Em alguns casos, complexidade é um pouco ponto de vista.
>>>>>
>>>>> Acho que entendi a abordagem do mantovani, mas pro meu caso
>>>>> específico, acho que é também o overhead, já que eu só valido 4 campos em
>>>>> uma situação eventual. Estou cogitando nem usar o Data::Manager.
>>>>>
>>>>> Se fosse um cazilhao de campos sendo validados constantemente, acho
>>>>> que valeira a pena.
>>>>>
>>>>> Mantovani, cuidado pra não ficar aparafusando pregos, certo!?
>>>>>
>>>>> []'s
>>>>>
>>>>>
>>>>> 2013/9/3 Solli Honorio <shonorio at gmail.com>
>>>>>
>>>>>> Sério mesmo Mantovani que vc acha que um sistema de fila é a solução
>>>>>> para eu validar se todos os campos de um formulário estão dentro do
>>>>>> aguardado para trabalhar no  banco de dados ?
>>>>>>
>>>>>> Mantovani, só posso dizer que estou orgulhoso de você... vejo que
>>>>>> você terá um excelente futuro na industria de tecnologia (coisa que eu não
>>>>>> tive), pois este é bem o comportamento dos vendedores de TI. Você está
>>>>>> agregando complexidade numa lugar que estou tentando agregar simplicidade
>>>>>> :D !!!
>>>>>>
>>>>>> Abraços,
>>>>>>
>>>>>> Solli Honorio
>>>>>>
>>>>>>
>>>>>>
>>>>>> Em 3 de setembro de 2013 14:58, Daniel de Oliveira Mantovani <
>>>>>> daniel.oliveira.mantovani at gmail.com> escreveu:
>>>>>>
>>>>>> 2013/9/3 Solli Honorio <shonorio at gmail.com>:
>>>>>>> > Lucas,
>>>>>>> >
>>>>>>> > Obrigado pelo retorno. Ontem a noite estudei o código do
>>>>>>> Data::Manager e ví
>>>>>>> > que realmente não rola fazer o que eu estava querendo fazer
>>>>>>> (passar uma
>>>>>>> > pilha de mensagem e receber de acordo com o contexto) e ai estou
>>>>>>> > encaminhando para a mesma solução que você.
>>>>>>>
>>>>>>> " o que eu estava querendo fazer (passar uma pilha de mensagem e
>>>>>>> receber de acordo com o contexto)"
>>>>>>>
>>>>>>> Shonorio, repetindo o AMQP se encaixa perfeitamente. Eu sugiro que
>>>>>>> você leia o link que eu te enviei. Se um serviço na sua máquina vai
>>>>>>> te
>>>>>>> poupar centenas de linhas de código, talvez nessa situação, nesse
>>>>>>> contexto obscuro no qual não foi definido pelo interlocutor seja uma
>>>>>>> boa.
>>>>>>>
>>>>>>> Se você acha que isso é demais para você, eu sinto muito que alguém
>>>>>>> com pelo menos 15/20 anos de experiência ainda não saiba formular uma
>>>>>>> pergunta. Perguntas genéricas, respostas genéricas. E ainda acho
>>>>>>> extremamente desnecessário o seu ataque gratuito, mas se você ainda
>>>>>>> não percebeu isso afasta as pessoas da lista.
>>>>>>>
>>>>>>> >
>>>>>>> > Como vc faz com o I18N ?
>>>>>>> >
>>>>>>> > O Renato Cron publicou um 'template'  (
>>>>>>> https://github.com/AwareTI/MyApp )
>>>>>>> > de como eles estão utilizando o Data::Manager. Estudei o código e
>>>>>>> achei
>>>>>>> > engenhoso, mas ainda quero manter um melhor controle do ResultSet
>>>>>>> porquê
>>>>>>> > quero devolver uma estrutura mais complexa de informação.
>>>>>>> >
>>>>>>> > Abraços,
>>>>>>> >
>>>>>>> > Solli Honorio
>>>>>>> >
>>>>>>> >
>>>>>>> >
>>>>>>> > 2013/9/3 Lucas Oliveira <lucasmateus.oliveira at gmail.com>
>>>>>>> >>
>>>>>>> >>
>>>>>>> >> Normalmente eu uso sempre com I18N mas da pra quebrar o galho
>>>>>>> assim
>>>>>>> >>
>>>>>>> >> <code>
>>>>>>> >> #!/usr/bin/env perl
>>>>>>> >>
>>>>>>> >> use common::sense;
>>>>>>> >> use Data::Manager;
>>>>>>> >> use Data::Verifier;
>>>>>>> >>
>>>>>>> >> my %msg_data = (
>>>>>>> >>    missing_name_last => 'Nao foi informado o campo name_last, seu
>>>>>>> idiota
>>>>>>> >> !',
>>>>>>> >> );
>>>>>>> >>
>>>>>>> >> sub messages { $msg_data{$_[0]} || $_[0] }
>>>>>>> >>
>>>>>>> >> my $dm = Data::Manager->new;
>>>>>>> >> my $dv = Data::Verifier->new(
>>>>>>> >>     filters => [ qw(trim) ],
>>>>>>> >>         profile => {
>>>>>>> >>             name_first => {
>>>>>>> >>                 required => 1,
>>>>>>> >>                 type     => 'Str',
>>>>>>> >>                 filters  => [ qw(collapse) ]
>>>>>>> >>             },
>>>>>>> >>             name_last => {
>>>>>>> >>                 required => 1,
>>>>>>> >>                 type     => 'Str',
>>>>>>> >>                 filters  => [ qw(collapse) ]
>>>>>>> >>             },
>>>>>>> >>             age  => {
>>>>>>> >>                 type        => 'Int'
>>>>>>> >>             },
>>>>>>> >>             sign => {
>>>>>>> >>                 required    => 1,
>>>>>>> >>                 type        => 'Str'
>>>>>>> >>             }
>>>>>>> >>         }
>>>>>>> >>     );
>>>>>>> >>
>>>>>>> >> $dm->set_verifier( name => $dv );
>>>>>>> >> $dm->verify( name => { name_first => 'Solli' });
>>>>>>> >>
>>>>>>> >> if (!$dm->success) {
>>>>>>> >>    print &messages( $_->msgid ).$/
>>>>>>> >>       foreach (@{ $dm->messages->messages });
>>>>>>> >> }
>>>>>>> >> </code>
>>>>>>> >>
>>>>>>> >>
>>>>>>> >> Em 02/09/2013, às 11:10, Solli Honorio <shonorio at gmail.com>
>>>>>>> escreveu:
>>>>>>> >>
>>>>>>> >> Pessoal,
>>>>>>> >>
>>>>>>> >> Estou tentando configurar uma mensagem padronização no
>>>>>>> Data::Manager, mas
>>>>>>> >> não está funcionando. Alguém aqui já utilizou o Data::Manager
>>>>>>> para saber se
>>>>>>> >> é possível fazer isto que eu quero ?
>>>>>>> >>
>>>>>>> >> O código abaixo, estou criando uma mensagem e adicionando no
>>>>>>> Data::Manger,
>>>>>>> >> porquê eu imaginei que quando ocorrer o problema dentro do escopo
>>>>>>> e msgid,
>>>>>>> >> eu teria o texto padronizado, mas o que estou recebendo é mais
>>>>>>> uma pilha de
>>>>>>> >> mensagem, mesmo quando não existe o erro.
>>>>>>> >>
>>>>>>> >> <code>
>>>>>>> >> #!/usr/bin/env perl
>>>>>>> >> use common::sense;
>>>>>>> >> use Data::Manager;
>>>>>>> >> use Data::Verifier;
>>>>>>> >> use Data::Printer;
>>>>>>> >>
>>>>>>> >> my $msg = Message::Stack->new;
>>>>>>> >> $msg->add({
>>>>>>> >>     msgid   => 'missing_name_last',
>>>>>>> >>     level   => 'error',
>>>>>>> >>     scope   => 'name1',
>>>>>>> >>     subject => 'name_last',
>>>>>>> >>     text    => 'Não foi informado o campo name_last, seu idiota
>>>>>>> !'} );
>>>>>>> >>
>>>>>>> >> my $dm = Data::Manager->new( { messages => $msg } );
>>>>>>> >> my $dv = Data::Verifier->new(
>>>>>>> >>     filters => [ qw(trim) ],
>>>>>>> >>         profile => {
>>>>>>> >>             name => {
>>>>>>> >>                 required => 1,
>>>>>>> >>                 type     => 'Str',
>>>>>>> >>                 filters  => [ qw(collapse) ]
>>>>>>> >>             },
>>>>>>> >>             age  => {
>>>>>>> >>                 type        => 'Int'
>>>>>>> >>             },
>>>>>>> >>             sign => {
>>>>>>> >>                 required    => 1,
>>>>>>> >>                 type        => 'Str'
>>>>>>> >>             }
>>>>>>> >>         }
>>>>>>> >>     );
>>>>>>> >>
>>>>>>> >>
>>>>>>> >> };
>>>>>>> >>
>>>>>>> >>
>>>>>>> >> $dm->set_verifier('name1', $verifier);
>>>>>>> >> $dm->verify('name1', { name_last => 'Honorio', name_first =>
>>>>>>> 'Solli' });
>>>>>>> >>
>>>>>>> >> my $results = $dm->get_results('name1');
>>>>>>> >> my $stack   = $dm->messages_for_scope('name1');
>>>>>>> >>
>>>>>>> >> say $results->success;
>>>>>>> >>
>>>>>>> >> say "Is invalid name_first ", $results->is_invalid('name_first');
>>>>>>> >> say "Is invalid name_last ",  $results->is_invalid('name_last');
>>>>>>>  # yes
>>>>>>> >>
>>>>>>> >> say "Is missing name_first ", $results->is_missing('name_first');
>>>>>>> # no
>>>>>>> >> say "Is missing is_missing ", $results->is_missing('name_last');
>>>>>>> # yes
>>>>>>> >>
>>>>>>> >> say "Missing count ", $results->missing_count;
>>>>>>> >>
>>>>>>> >> say "Count : ",  $stack->count ;
>>>>>>> >> p $stack->get_message( 0 );
>>>>>>> >> p $stack->get_message( 1 );
>>>>>>> >>
>>>>>>> >> </code>
>>>>>>> >>
>>>>>>> >>
>>>>>>> >> --
>>>>>>> >> "o animal satisfeito dorme". - Guimarães Rosa
>>>>>>> >> =begin disclaimer
>>>>>>> >>   Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>>>>> >> SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>>>>> >> L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>>>>>> >> =end disclaimer
>>>>>>> >>
>>>>>>> >>
>>>>>>> >>
>>>>>>> >> =begin disclaimer
>>>>>>> >>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>>>>> >>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>>>>> >>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>>>>>> >> =end disclaimer
>>>>>>> >>
>>>>>>> >
>>>>>>> >
>>>>>>> >
>>>>>>> > --
>>>>>>> > "o animal satisfeito dorme". - Guimarães Rosa
>>>>>>> >
>>>>>>> > =begin disclaimer
>>>>>>> >    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>>>>> >  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>>>>> >  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>>>>>> > =end disclaimer
>>>>>>> >
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>>
>>>>>>> -dom
>>>>>>>
>>>>>>> --
>>>>>>>
>>>>>>> Daniel de Oliveira Mantovani
>>>>>>> Business Analytic Specialist
>>>>>>> Perl Evangelist /Astrophysics hobbyist.
>>>>>>> +55 11 9 8538-9897
>>>>>>> XOXO
>>>>>>> =begin disclaimer
>>>>>>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>>>>>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>>>>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>>>>>> =end disclaimer
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> "o animal satisfeito dorme". - Guimarães Rosa
>>>>>>
>>>>>> =begin disclaimer
>>>>>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>>>>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>>>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>>>>> =end disclaimer
>>>>>>
>>>>>>
>>>>>
>>>>> =begin disclaimer
>>>>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>>>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>>>> =end disclaimer
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> "o animal satisfeito dorme". - Guimarães Rosa
>>>>
>>>> =begin disclaimer
>>>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>>> =end disclaimer
>>>>
>>>>
>>> =begin disclaimer
>>>   Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>> SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>> L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>> =end disclaimer
>>>
>>>
>>>
>>> =begin disclaimer
>>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>> =end disclaimer
>>>
>>>
>>
>
> =begin disclaimer
>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
> =end disclaimer
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.pm.org/pipermail/saopaulo-pm/attachments/20130904/6b4ec52d/attachment-0001.html>


More information about the SaoPaulo-pm mailing list