Catalyst::View::TT has a render

03 June 2006


Catalyst::View::TT 从 0.23 起将多了一个函数叫做 render. 一个最常见的用法是:
   $c->email(
header => [
To => '[email protected]',
Subject => 'A TT Email',
],
body => $c->view('TT')->render($c, 'email.tt', {
additional_template_paths => [ $c->config->{root} . '/email_templates'],
email_tmpl_param1 => 'foo'
}
),
);
以前我们经常得用 SubRequest 来做这事。
可看起来 render 似乎更干净一些。:)

WWW::Mechanize++

27 May 2006


I should suggest u guys all to have a try of WWW::Mechanize
WWW::Mechanize is damn useful. I use it to fecth all contacts information from mail suppliers such as Yahoo, Hotmail, Gmail, 163, Sina, Sohu and Tom.
ya, many thanks for petdance, it works great! (though all the supplier are using javascript a lot, a pity that WWW::Mechanize don't support javascript)

and TT2 ++, a new version of 2.15 is released. TT is my lovest template system ever.
http://search.cpan.org/src/ABW/Template-Toolkit-2.15/Changes

Catalyst and FormValidator::Simple

21 May 2006


检验用户输入信息的正确性几乎是所有 Web 编程者都需要做的事。有句话是永远不要相信你的用户。每一个用户都可能是骇客。
Catalyst 中我最喜欢的检测插件是 Catalyst::Plugin::FormValidator::Simple
我可以用个简单一点的例子来说明一下。

假设最简单的用户注册。一个用户名 6-12 个字符。密码 6-20 个,输入两次,两次都一样。 email 一个。要求大致正确。用户名和 email 必须与数据库里已有的不冲突。
Controller 大致为这样子:
sub register : Global {
my ( $self, $c ) = @_;

$c->stash->{template} = 'user/register.html';

return unless ($c->req->param('process'));

# execute validation.
$c->form(
username => [[ 'DBIC_UNIQUE', $c->model('DBIC')->resultset('User'), 'username' ], qw/NOT_BLANK ASCII/, [qw/LENGTH 6 20/] ],
password => [qw/NOT_BLANK/, [qw/LENGTH 6 12/] ],
email => [qw/NOT_BLANK EMAIL_LOOSE/, [qw/LENGTH 5 20/], [ 'DBIC_UNIQUE', $c->model('DBIC')->resultset('User'), 'email' ] ],
{ passwords => ['password', 'confirm_password'] } => ['DUPLICATION'],
);

my $result = $c->form;
return if ( $result->has_error );
$c->form 就是 Catalyst::Plugin::FormValidator::Simple 所提供的函数。DBIC_UNIQUE 检验机制是由 FormValidator::Simple::Plugin::DBIC::Unique 所提供的。主要用于检测表中的某一字段是否是 unique 独一的。我们所看到的如 NOT_BLANK LENGTH EMAIL_LOOSE DUPLICATION 都是 FormValidator::Simple 所自带的检测机制。还有 DATE 用于检测输入的日期是否合法,Regex 等。可以查阅 perldoc FormValidator::Simple
上面的是检查,然后如果出错要把错误显示出来。这里我觉得有点不方便。比如说 username 到底是违反了哪一条。 $c->form->error('username') 返回的是一个匿名数组,如 [ 'DBIC_UNIQUE', 'LENGTH' ] 我的习惯是将错误消息显示在 username text 输入框的旁边,而不是把所有的错误消息都放一起。这样判断起来很麻烦。我差不多得这么写:
<input type='text' name='username' length='12' />
[% FOREACH type IN c.form.error('username') %]
[% IF type == 'DBIC_UNIQUE' %]
This username is used by another one.
[% END %]
....
[% END %]
这种是比较愚笨的方法。我对这个也没用过几次,所以可能有好办法还没发现。perldoc 中提到了用 yml 来定义错误信息,或者这个比较可行,但是我不太喜欢,因为我在做多语言版本的 Forum

或许我得再仔细研究下错误怎么显示才是最方便的。:) later~

update
我发现这样子是可行的:
 [% IF c.form.error('username') %]
[% IF IF c.form.error('username', 'DBIC_UNIQUE') %]
This username is used by another one.
[% ELSE %]
username should be 6-20 chars.
[% END %]
[% END %]

YAPC::Asia 2006 video download

17 May 2006


http://www.archive.org/search.php?query=subject:%22yapc%22

u know it's interesting. It has haskell, Catalyst, JSAN and Ajax, Jemplate and Perl 6.
and Damain Conway, Audrey Tang, Larry Wall and Ingy dot Net are present.

:)

Mother's Day

14 May 2006


today is mother's day, please don't forget it. :)

use Date::Holidays::CN;

my ($year, $month, $day) = (localtime)[ 5, 4, 3 ];
$year += 1900;
$month += 1;
if (my $holidayname = is_cn_holiday( $year, $month, $day )) {
print $holidayname;
}

$c->forward stuff

11 May 2006


Catalyst 的 forward 并不如想象中的那么好。
第一,它不能返回 array, 它只能返回 $scalar
第二,当它返回 undef 的时候,它实际上返回的是一个数值 0

第二是个很奇怪的事,然后我看了看 Catalyst 的代码,发现都是这一句的错。

Catalyst.pm 1121
eval { $c->state( &$code( $class, $c, @{ $c->req->args } ) || 0 ) };

我给他们的 mailing list 发了个消息:http://lists.rawmode.org/pipermail/catalyst/2006-May/007418.html

Yuval Kogman 回复说原因是为了兼容以前的代码。以后会有一个新的 call 方法推出,将支持 array 和返回 undef
而 Perrin Harkins 和 Matt S Trout 建议不要用 forward 而是用普通的 subroutine, 只是将第一个参数 $c 传过去。这也是非常好的一个方法,我可不要钻牛角尖。:)

sri left Catalyst

04 May 2006


诸如通告所说,Sri 离开了 Catalyst 项目。http://lists.rawmode.org/pipermail/catalyst/2006-May/007250.html
该项目的其他主要开发人员都没变。

他将开始一个新的 MVC 项目。名字可能是 Mojo.
不过 CPAN 上有个原型,叫 ReAction, 可以从这下过来看看:http://search.cpan.org/~mstrout/Reaction-0.001000_001/
ReAction 将严重依赖于 Moose.
Moose 是个差不多类似于 Perl 6 OO 的 Perl 5 的实现。由 Pugs 的开发人员 Stevan Little 写的。
在 Win32 下要安装 Moose, 得去下 ActivePerl 5.8.8,因为需要 List::Utils 1.18

据我推测,Mojo 或者 ReAction 将不像 Catalyst 那样支持任意的 Model 而是用了 DBIx::Class. 而且将会采用 Dojo 作为基础的 javascript 库。
虽然没有 Catalyst 那么容易扩展,不过我还是挺期待 sri 的作品的。
当然,目前基于 Catalyst 的项目我也没有打算要迁移到新的 MVC 上。

百花争放,这是个好现象。:)

Catalyst newsgroup

28 April 2006


ok, 我得说我比较喜欢 newgroup 的形式。很幸运的是,今天看 mailing archive 的时候看到了 news.gmane.org 里有一个转载的 gmane.comp.web.catalyst.general 组。
我平时就用 Thunderbird 来订阅 newsgourp. 一般而言我只订阅两个服务器,一个是 news.gmane.org 另一个是 news.yaako.com
news.gmane.org 里还有 modperl 的组:gmane.comp.apache.mod-perl

喜欢的话我还是推荐试下 newgroup. I love it very much.

javascript XML parser

25 April 2006


老板要求 Ajax 的 reponse 是 XML, 所以要找一个解析 xml 的 javascript 库。
因为已经用了 JSAN , 所以就在那找了个 XML.ObjTree
我用 XML::Writer 来构造 xml response. 比如说我们的 response 为
<xml><message>OK</message></xml>
然后 javascript 的代码大概为:
function ajax() {
var myAjax = new Ajax.Request( url, {
method: 'get',
parameters: pars,
onSuccess: showResponse,
} );
}
function showResponse(request) {
response = request.responseText;

JSAN.use('XML.ObjTree');
var xotree = new XML.ObjTree();
var tree = xotree.parseXML( response );

$('message').innerHTML = tree.xml.message;
}
这是针对回复只有一个 <message> 的。如果是多个 messages, javascript 的代码可以为:
for (i = 0; i < tree.xml.message.length; i++) {
唯一有点麻烦的是,我们期待回复的是 message array, 但是只有回了一个 message, 那这个 for 会失败,但是有 tree.xml.message 所以在 for 后面得加个
// ugly hack, for only one
if (tree.xml.message) {

Have fun!

MySQL SELECT condition

20 April 2006


昨天写代码的时候发现 MySQL 的 SELECT 条件多反而比条件少要快很多。
其实我可以用
SELECT * FROM comment WHERE reply_to = ?
来得到我想要的结果。但是我用
SELECT * FROM comment WHERE reply_to = ? AND object_id = ? AND object_type = ?
时,结果是一样的,但是速度从 7-9s 提高到 0.07-0.09, 速度提升了百倍。这东西可能在表的 rows 比较少的时候效果不明显。但在 rows 是 4,530,000 时就有百倍的提升。

又学会一手。