Sunday, December 17, 2006

my first Catalyst Action

Catalyst::Action 是 Catalyst 里的另一种代码复用技术。

我写的一个功能是记录一些 path 信息:比如 get, post, 还有页面载入的时长。
这个页面载入的时长是在 begin 时用 Time::HiRes 记录一个 gettimeofday, 然
后在 end 结束后再用 tv_interval 来获取时长。
“记录 path 信息”要写的地方在 return 之前。比如有 $c->res->body 或
$c->res->location 的时候直接返回了,否则在 $c->view 后返回。这是常见的一
个 sub end 的写法。
如果不用 Catalyst::Action 的话,可以有一些弊端如,sub end 里要写两次(两
个 return 之前),还有如果有很多个 end 代码就可能会写到很多地方。
第二个好处是 Catalyst::Action 所谓的真正的复用。只要是 sub end 在后面加
上 :ActionClass 就会复用之个 Action 的代码。
第一个好处只是 NEXT 所带来的。

可能的代码:
Before:
# Root.pm
sub begin : Private { my ($self, $c) = @_; $c->stash->{start_t0} =
[gettimeofday]; }
sub end : Private { my ($self, $c) = @_;
if ($c->res->body || $c->res->location) {
$c->model('Log')->log_path($c, tv_interval(
$c->stash->{start_t0}, [gettimeofday] ) ); # log path
return;
}
# code here
$c->forward($c->view('TT'));
$c->model('Log')->log_path($c, tv_interval( $c->stash->{start_t0},
[gettimeofday] ) ); # log path
}
如果有其他 pm 的 sub end 覆盖了 Root.pm 的 end 的话,那还要在那个
sub end 里加上 log_path.

而 Catalyst::Action 的复用会很方便:
After:
package Catalyst::Action::PathLogger;

use strict;use warnings;
use base 'Catalyst::Action';
use Time::HiRes qw( gettimeofday tv_interval );

sub execute {
my $self = shift;
my ( $controller, $c ) = @_;

$self->NEXT::execute( @_ );

$c->model('Log')->log_path($c, tv_interval( $c->stash->{start_t0},
[gettimeofday] ) );
}
而 Root.pm 的 sub end 将不在用 :Private 而是 sub end :
ActionClass('PathLogger') 其他 pm 如果有 sub end 也可以这么写。

quite easy and reusable. have fun! :)

Labels:

0 Comments:

Post a Comment

Links to this post:

Create a Link

<< Home