Catalyst: dicas e truques

Wallace Reis
Publicado em 01/03/2012

Catalyst: dicas e truques

Caso esteja iniciando no Catalyst, sugiro fortemente que vá primeiro à seção Leia mais|#Leia_mais no fim deste artigo onde encontrará links úteis com bons artigos introdutórios (ao menos os dois primeiros).

Do contrário, vamos lá...

Capture os warnings e lance à lua

Pode-se apenas usar o Catalyst::Plugin::LogWarnings, porém ele só permite o logging dos warnings usando o objeto Catalyst log e só captura os que veem do seu código deixando de fora qualquer possível warning que venha do código do Catalyst. Supondo que queira-se mais do que isto, podemos extender o método do Catalyst chamado handle_request através de uma role para sua classe da aplicação (meio recomendado) ou diretamente nesta classe.

    around handle_request => sub {
      my ( $orig, $self ) = ( shift, shift );
      return do {
        local $SIG{__WARN__} = sub {
          chomp(my $warn_msg = shift);
          # ...
        };
        $self->$orig(@_);
      };
    };

Então, você pode logar a $warn_msg usando o objeto Catalyst log ($self->log->warn($warn_msg)), enviar por email usando um model, tweetar, blogar, ou seja, fazer o que você quiser.

Adicionando métodos úteis ao Catalyst::Response

Digamos que gostariamos de extender o nosso objeto de resposta com por exemplo métodos de checkagem como os que temos em HTTP::Status...

    package MyApp::TraitFor::Response::HTTPStatus;

    use Moose::Role;
    use namespace::autoclean;
    use HTTP::Exception;

    has _status_as_exception => (
      is => 'ro', lazy => 1, builder => '_build_status_as_exception',
      handles => [qw(is_info is_success is_redirect is_error is_server_error
        is_client_error)],
    );

    sub _build_status_as_exception { return HTTP::Exception->new(shift->status) }

    1;

Depois, usa-se o CatalystX::RoleApplicator para aplicar esta nova role para a classe de resposta:

    __PACKAGE__->apply_response_class_roles('MyApp::TraitFor::Response::HTTPStatus');

Desta forma, podemos fazer em nossa aplicação...

    if ( $c->response->is_error ) {
        # ...
    }

Gere uma página customizada para os erros fatais

O Catalyst tem uma página padrão (diga-se de passagem "feinha") para quando encontra-se um error nas aplicações, mas podemos extendê-lo de forma a produzir uma página que obdeça o nosso layout com uma implementação customizada para o método finalize_error.

    use Try::Tiny;

    sub finalize_error {
      my $self = shift;
      my $res = $self->response;
      unless ( $res->is_server_error ) {
        $res->status(500);
      }

      my $body = try {
        $self->view('TT')->render($self, 'error/500.tt')
      } catch { 'Desculpe, volte novamente mais tarde.' };
      $res->body($body);
    }

Ou pode-se usar o Catalyst::Plugin::ErrorCatcher e extender mais ainda o o processo de captura e manipulação de erros.

Ative informações de debug...

apenas quando realmente precisa-se delas através de um valor verdadeiro para a variável de ambiente CATALYST_DEBUG ou <MYAPP>_DEBUG, assim você não precisa mais do flag -Debug na instrução use Catalyst.

No caso apenas das estatísticas...

defina um valor verdadeiro para a variável de ambiente CATALYST_STATS ou <MYAPP>_STATS, assim você não precisa mais do flag -Stats.

Obtenha informações sobre o browser dos seus usuários

Pode-se usar o Catalyst::TraitFor::Request::BrowserDetect para realizar a detecção automática dos browsers retornando um objeto HTTP::BrowserDetect o qual nos fornece métodos úteis sobre o agente dos usuários.

Gostaria de usar o Test::WWW::Mechanize::Catalyst...

porém este não fornece um objeto contexto da aplicação como o Catalyst::Test em ctx_request()? Podemos resolver isto desta forma:

      use Test::More;
      use Test::WWW::Mechanize::Catalyst 'MyApp';

      my $ctx;
      my $myapp_meta = MyApp->meta;
      my %immutable_options = $myapp_meta->immutable_options;
      $myapp_meta->make_mutable;      $myapp_meta->add_after_method_modifier(
        'dispatch' => sub { $ctx = shift }
      );
      $myapp_meta->make_immutable(%immutable_options);

      my $mech = Test::WWW::Mechanize::Catalyst->new;
      {
        $mech->get_ok('/');
        my $browser = $ctx->request->browser;
        diag($browser->version);
      }

      # ...

Como posso controlar o log na execução de testes?

Algumas vezes faz-se necessário que seja desativado alguns níveis do log, pois é sabido, ou seja, é esperado que nestes momentos as requisições gerem erros.

      my $myapp_meta = MyApp->meta;
      my %immutable_options = $myapp_meta->immutable_options;
      $myapp_meta->make_mutable;
      $myapp_meta->add_before_method_modifier(
        'handle_request' => sub {
          my $log = shift->log;
          $log->disable('error', 'fatal');
        }
      );
      $myapp_meta->make_immutable(%immutable_options);

      # ...

Leia mais

Autor

Wallace Reis <http://about.me/wallacereis>

blog comments powered by Disqus