?

Log in

No account? Create an account
PerlChina-Catalyst-Study-Group's Journal
 
[Most Recent Entries] [Calendar View] [Friends]

Below are the 20 most recent journal entries recorded in PerlChina-Catalyst-Study-Group's LiveJournal:

[ << Previous 20 ]
Saturday, October 28th, 2006
10:31 pm
[yourselfzm]
想在Catalyst中输出PDF格式文件,但中文总显示乱码
my $name = encode("euc-cn",'中文'); //现在就是不知道这个euc-cn应该换成什么才能显示中文。
my $pdf = PDF::API2->open('ns.pdf');
$pdf->saveas("ns001.pdf");
$pdf = PDF::API2->open("ns001.pdf");
my $page = $pdf->openpage(1);
$page->mediabox('A4');
my $fnt = $pdf->corefont('Courier');
my $gfx = $page->gfx;
$gfx->textlabel(220,690,$fnt,20,$name);
$pdf->update;


不知道如何解决中文输出到PDF格式文件中的问题,谢谢指导!
Tuesday, January 17th, 2006
5:44 pm
[zjl_perl]
看Catalyst5.61的intro时有三个问题
1,如何不重启myapp_server.pl而直接预览myapp?
(catalyst中说
# built in testserver -- use -r to restart automatically on changes
script/myapp_server.pl

2,在 examples of the order in which the various built-ins would be called 之中。例子中:

a request for /foo/foo

MyApp::begin
MyApp::auto
MyApp::Controller::Foo::default # in the absence of MyApp::Controller::Foo::Foo
MyApp::end

在MyApp::begin之前为什么不执行MyApp::Controller::foo::foo::begin呢?
在MyApp::auto之后为什么不是执行MyApp::Controller::foo::auto 呢?
这个执行顺序有什么假设前提吗?

3,可以通过create controller来创建一个对URL的action,比如我可以通过
myapp_create.pl controller Library::Login 来创建对http://localhost:3000/library/login的访问;也可以通过先 myapp_create.pl Library 然后在library.pm中定义sub login : Path {} 来创建同样的URL访问。那么这两者之间有什么不同呢?
Thursday, December 15th, 2005
4:50 pm
[joe_jiang]
chinese catalyst calendar launched
圣诞之前简称 CCC 的这个 perlchina 网站开始了 Catalyst 大事记中文翻译项目,以 catalyst 自己来展示自己的近况,实际上是用一个活动 demo 的概念来宣传自己。

希望大家能够多多参与,方法是关注英文版本的 catalyst calendar,向 chunzi 申请 svn 账户。然后 check in 你某一天的翻译。

这个想法真有趣,希望有更多如此有创意的事情每天发生。
Saturday, December 10th, 2005
1:09 pm
[fayland]
Template customized Filters
昨日写了点 TT 内置过滤器(Template builtin Filters),现在有兴趣讲讲自己怎么写一个 filter.

昨日说了 filter 分为两种:一种为静态,一种为动态。二者的区别是静态不接受任何参数,如 html, collapse, trim, ucfirst, lower 等,而动态接受参数,如 format('%0.3f'), indent("> ")
而放置 filter 的地方也分为两种,一种是直接放在代码里,另一种是写为 Template::Plugin::Filter 的子类模块。
我打算先讲直接放在代码里的。

Static Filters

静态过滤器是最简单的。我们用个最简单的 filter 来写个 lower/ucfirst 过滤器。
sub ucf {
   my $text = shift;
   $text = ucfirst lc $text;
   return $text;
}
my $tt = Template->new({
FILTERS => {
'ucf' => \&ucf,
'lcf' => sub { lcfirst uc shift; },
},
});
上面就是静态过滤器的两种形式。一种是 subroutine 子程序的引用,一种是匿名子程序。
无论是哪种子程序都接受一个 shift 过来的字符串,然后返回一个 $string.
注册 filters 使用 FILTERS 参数。而 Catalyst 可以这么写:
package Eplanet::V::TT;

use strict;
use base 'Catalyst::View::TT';

__PACKAGE__->config->{FILTERS} = {
   'ucf' => \&ucf,
   'lcf' => sub { lcfirst uc shift; },
};

而 filter 的应用与内置的是一样的。
[% FILTER ucf %]template is great[% END %]
输出 Template is great
[% | lcf %]template is great[% END %]
输出 tEMPLATE IS GREAT

Dynamic Filters

动态的是可以接受参数的。它的注册方法与静态的略微有点不同:
my $tt = Template->new({
FILTERS => {
'ucf' => \&ucf, # our trusty static filter
'cut' => [ \&cut, 1 ], # our dynamic filter
},
});
第一种是我们所熟悉的静态过滤器,而第二种就是动态过滤器。它传递的一个数组引用且第二个参数为 1.
我们所熟悉的静态过滤器还有种写法:
'ucf' => [ \&ucf, 0 ],
这与 'ucf' => \&ucf, 是一样的。

动态过滤器所定义的子程序大致为这样子的:

sub cut {
my ($context, $len) = @_;
return sub {
my $text = shift;
$text = substr($text, 0, $len);
return $text;
}
}
[% | cut(5) %]template is great[% END %]
输出为 templ
动态过滤器里第一个参数 $context 是 Template::Context 的一个对象,这个涉及到 Template 的内核我也不太懂。
第二个参数 $len 这里就是 5.
它返回的必须是一个程序的引用。跟静态的差不多。不过这个返回的子程序引用是个闭包。

这样我们差不多说清楚了 filter 怎么写了,下面说说怎么写一个模块。

Template::Plugin::Filter

package MyTemplate::Plugin::Filter::Textile;

use strict;
use Template::Plugin::Filter;
use base qw(Template::Plugin::Filter);
use Text::Textile;

sub filter {
   my ($self, $text) = @_;
   $text = Text::Textile::textile($text);
   return $text;
}

1;

这是一个标准的写法:use base qw(Template::Plugin::Filter); see Template::Plugin::Filter
然后覆盖它的 filter 子程序。参数为 my ($self, $text) = @_; 返回字符串。一个静态过滤器。
而注册的写法为:
my $tt2 = Template->new({
PLUGIN_BASE => 'MyTemplate::Plugin::Filter'
PLUGINS => {
Textile => 'MyTemplate::Plugin::Filter::Textile',
},
});
因为 Filter 是 Plugin 的一种,所以我们这里设置的是 PLUGINS.
Catalyst 的 ::V::TT 写法类似:
__PACKAGE__->config->{PLUGIN_BASE} = 'MyTemplate::Plugin::Filter';
__PACKAGE__->config->{PLUGINS} = {
   Textile => 'MyTemplate::Plugin::Filter::Textile',
};
而实际用则这么写:
[% USE Textile %]
[% FILTER $Textile %]this is _like_ *so* *cool*[% END %]
效果为:

this is like so cool

Conclusion

这就是大致上一般的 template toolkit filter 的知识。如有错误请指正。Enjoy!

cross-post: http://www.fayland.org/journal/Template_customized_Filte.html
1:06 pm
[fayland]
Template builtin Filters
所谓 filter, 过滤器。想像一下咖啡的过滤器,想像下香烟的过滤嘴。Template 的过滤器也差不多。
我打算先介绍下 TT 内置的一些 filters, 然后明天介绍下如何写自己的 filter.

builtin filters

恐怕最最常用的一个 filter 就是 html, filter 的用法有以下几种:
[% FILTER html %]
<script language="JavaScript" type="text/javascript">
<!--
document.writeln("Hello, world");
//-->
</script>
[% END %]
TT 给懒人们弄了个简单的符号 | 用以代替 FILTER 这六个英文字母。所以你也可以这么写:
[% | html %]
另一种是外来的一个变量或者在其他地方定义的一个变量。比如我们在其他的模版里定义了:
[% output = '<script language="JavaScript" type="text/javascript">
<!--
document.writeln("Hello, world");
//-->
</script>' %]
到时候我们输出的话可以这么写:
[% output | html %]
# or [% output FILTER html %]
我们还可以使用多个 filters.
[% output | html | truncate(30) %]
以上差不多就是所有 filter 的用法。

    另外的一些内置 filter 有
  • format format 与 html 不同,它是一个动态 filter, 可以接受参数。比如:(用途类似 sprintf)
    [% pi = 3.1415926536 %]
    [% pi | format('%0.3f') %]
    这样输出的结果为 3.142
  • collapse 这个内置的 filter 将所有的所有多于一个空格的大空白过滤为一个空格。如:
    [% FILTER collapse %]
    You'll love

    it, it's a way

    of life.
    [% END %]

    输出的结果为:You'll love it, it's a way of life.
  • eval / evaltt 将变量作为 TT 模版来运行。这个变量一般是从外面传进来的。比如:
    my $vars  = {
    fragment => "The cat sat on the [% place %]",
    };
    $tt->process($file, $vars);
    || die $tt->error( );
    [% fragment | eval %]
    能将 [% place %] 用变量 place 代替掉。evaltt 跟 eval 是等同的。
  • indent(pad) 用于缩进。比如我们回复信件的时候一般在原来的信件内容前加“> ”,在 TT 中就可以这么写:
    [% FILTER indent("> ") -%]
    Dear Fayland,

    Would u help me to ..

    Best Regards,
    [% END %]

    输出的结果为:
    > Dear Fayland,
    >
    > Would u help me to ..
    >
    > Best Regards,
  • lcfirst/ucfirst/lower/upper 如字面意思所写的,首字小写/大写/全部小写/大写
  • remove(string) 用正则表达式移除一些字符。如:
    [% string = "Hello, I must be going.";
    string | remove("e") %]
    输出:Hllo, I must b going. 我们还有更复杂的正则表达式:
    [% string = "Hello, I must be going.";
    string | remove("(?x) # whitespace is not important
    (?<=H) # an 'H'
    e # strip the 'e'!
    (?=ll) # followed by 'll'
    ") %]
    这个表达式用于匹配以 H 开头后接 e 再接 ll 但不移除 H 和 ll 的表达式。
  • replace(search, replace) 以 remove 不同的是代替。remove 查不多是将 replace(string, '')
    [% string = "Hello, I must be going.";
    string | replace("e", "u") %]
    输出:Hullo, I must bu going.
  • repeat(iterations) 重复几次。
    [% FILTER repeat(5) %]
    I love Perl only less than my girl.
    [% END %]
    将这句重复输出 5 次。
  • trim 将前后空格去掉。
  • truncate(length) 截取前 length 个字符。我们常见的一个描述然后 Read More.. 就可以这样子:
    [% FOREACH result = results %]
    * [% result.description | truncate(24) %]
    <a href="[% result.link %]">Read more</a>
    [% END %]
  • uri 将 uri 变为浏览器所喜欢的形式。类似 URI::Escape 的功能。
  • 还有其他一些,查看 TT 的 documents
文章有点长,怎么自定义 filter 明天在另一篇中写。

cross-post: http://www.fayland.org/journal/Template_builtin_Filters.html
1:04 pm
[fayland]
Catalyst config YAML
我们一般写代码都应当避免一种称为 hardcode 硬代码。
所谓的 hard code 是指将代码拷贝到另外的地方你必须更改其中的某些代码。
比如你写了一个 Controller, 里面使用了类如 '/home/fayland/eplanet' 这样的字符串。当你将这个代码迁移到其他目录或其他机子的时候,人们必须要改变这个字符串才能正常运行该程序。我们管这些字符串为 hard code.
一种避免 hard code 的方法就是将所有的这些字符串用一个配置文件包括,这样人们就只需要修改下配置文件就能运行程序而不是修改程序的源代码。
这种避免 hard code 的方法尤其在源码协作/ Subversion 时最为有用。每人拥有相同的源码不同的配置文件,这样不会对源码造成冲突。

最近的 CatalystAdvent 就介绍了怎么在 Catalyst 中使用 Day 9 - YAML, YAML, YAML!.
原来在 MyApp.pm 中这么写的代码:

 __PACKAGE__->config( name => 'MyApp', 'View::TT' => { EVAL_PERL => 1 } );
将修改为:
use YAML ();    
__PACKAGE__->config( YAML::LoadFile( __PACKAGE__->path_to('myapp.yml') ) );
而 myapp.yml 文件的结构为:
---
name: MyApp
View::TT:
EVAL_PERL: 1
不过该 Advent 里没有介绍怎么写 yml 文件。对于复杂的希哈里套数组再套希哈什么的结构很容易让人写错。
我一般的习惯都是写一个 pl 文件来创立该 yml 文件。比如在 Person 项目中我在 tools 里是这么写的:
#!/usr/bin/perl
use strict;
use warnings;
use FindBin;
use YAML();

# CHANGE THIS LINE, THEN RUN IT!
my $DIR = $FindBin::Bin;
$DIR =~ s!/tools/?!!; # /usr/local/apache/www/Person
print $DIR;

my %a = (
   name => 'Person',
   root => "$DIR/root",
   templates => "$DIR/templates",
   member_images => "$DIR/root/member",
   email => {
       enable => 1, # local machine can be 0
       charset => 'utf8',
       smtp_host => '61.152.95.132',
       prefix => '[PerlChina]',
   },
   dsn => 'dbi:mysql:person',
dsn_user => 'root',
dsn_password => '',
images_folder => "$DIR/captcha/images",
   data_folder => "$DIR/captcha/data",
   output_folder => "$DIR/root/captcha",
   # if u run this in your local machine, CHANGE IT
   base_site => 'http://localhost:3000/',
);

YAML::DumpFile("$DIR/Person.yaml", \%a);
print ', DONE!';

1;

这样我们用 YAML::DumpFile 出一个 yml 文件,然后用 LoadFile 导进一个。非常的绝配。 :-)
详细的查看 http://dev.perlchina.org/cgi-bin/trac.cgi/browser/trunk/Person/tools/YAML_Create.plhttp://dev.perlchina.org/cgi-bin/trac.cgi/browser/trunk/Person/lib/Person.pm

cross-post: http://www.fayland.org/journal/Catalyst_YAML.html
Thursday, November 24th, 2005
2:31 pm
[joe_jiang]
Catalyst 面面俱到
The Many Ways Of Catalyst 面面观
=========================

Installation 草
  Linux 水草
  Windows 芹菜
  MacOS 竹子
  
Parts of Catalyst (not technical) 才怪
  MVC 人、口、手
    Model 人
    View 口
    Controller 手
  Helpers 帮助脚本概念来自 RoR
    Scripts .. 本
  Engine 脚
  Dispatcher 派
  Context 境
  Stash 库
  Request 求
  Response 答
  Plugins 挂

Application Design 应用设计
  Directory and File Structure 目录树
    Path Handling 寻径
  Components 组件
  Configuration 配置
    With an external file 外部配置
  Actions 动作
    Turning on Case Sensitivity 大小写过敏
    Private Actions 私有动作
      Calling Order 调用次序
      begin 开始
      auto 自动
      end 结束
      index 索引
      default 默认
    With absolute path 绝对路径
      Global 全局
      Regex 正则语言
      Path 路径
    With relative path 相对路径
      Local 本地
      LocalRegex 正则方言
    Dispatch Order 派发顺序
  How to set up 案例
    a new Catalyst Application 新应用
    a stub Database Administration (Scaffold) 骨感 DBA 应用
    a new View 加口
    --"-- Controller 加手
    --"-- Model 加人
  The Catalyst Startup 启动
  Control Flow 流控
    Forwarding execution to a private action 局部传动
    Detaching, or Foward-without-return 一去不返
    Redirecting the Browser 口是心非
  Once upon a Request 入不敷出
    On demand parsing of input 量入为出
  Logging 记帐
  Accessing Query Parameters 输入参数
  Output出
    Directly 直接出门
      Setting the output 选择着装
      Writing to the output filehandle 带上包
    How Views Work (and how to subclass, etc) 口红怎么用
    Templates 印模
      How to set which template to render 选择打印格式
      Using the stash to get the data to the view 挤牙膏
      Plugins 挂件
    Setting Headers 帽子
      Cookies 饼干
      Content Type 糖果
  Data 钱
    Verifying User Input 验钞
      Plugins 验钞机
    How Models Work (and how to subclass, etc) 怎么用钱
    Database Access 钱库
      DBIx::Class 比较 CDBI
        Automatic Model Setup (Loader) 天上掉馅饼
  Error Handling 假钞
    Exceptions 报警
      Making your own 私了
    At the end of a Request 别忘了发票
    In Templates 回家
  Sessions 报销
    Plugins 
    Storing Persistant Data 实物为证
    Pitfalls In Using Sessions 损公肥私
  Authentication 排队
    Plugins 照片
    Basic Auth 密码
    Via Form 填表
  Authorization 签名
    Access Control Lists 喜好
    Roles 角色
    Model Ownership 主人
  AJAX 火
  RSS and Atom Feeds 水
  XMLRPC 土
  Subrequests 
  Sending Mails 油
  Plugins 
    How they work 
    What they can do 
    How to Write 
    
Development 旅游
  The Shipped Server 上船
  Debugging Output 晕船
    Showing Internal Actions 呕吐
  
Deployment 住店
  Packaging your App 打包
  FastCGI 托运
  mod_perl 推车
  Can I run my App as CGI? 拎包
  Proxy Support 寄包

Updates 休息
  Updating your scripts 看书

How To Get Help 手册
Monday, November 14th, 2005
10:00 am
[joe_jiang]
Catalyst version 5.5
* Improved docs 改进了文档
* Auto-restarting development server 自动重启的开发用服务器
* Built in serving of static files 内建的静态文件服务
* c.uri_for glue to clean up your templates 补充了 c.uri_for 用来清理模板
* Upload progress support (on all platforms) 上载进度条支持(跨平台)
* Support for passing a file handle to the response body 支持在应答体内传递文件句柄
* new index action 新的索引动作
* killing logging of static files 静态文件的 log 屏蔽
* $c->controller, $c->model and $c->view shortcuts for $c->comp
* Did I mention improved docs?


*IMPORTANT* The Apache engines have been moved to a separate package
for this release. Please install Catalyst::Engine::Apache if you
need Apache support.
Thursday, November 10th, 2005
12:36 pm
[chunzi]
Catalyst-5.49_04
可能是最后一次的 Catalyst 5.50 之前的测试版本。如果 CPAN 上还没有,可以到这里下载

http://pause.perl.org/incoming/Catalyst-5.49_04.tar.gz

本次更新:

- 现在 context, dispatcher, engine, request 和 response 类都可配置
- 增加了 $c->stack.
- 修复了 dispatcher (忽略未知的 action 属性)
- 改善了启动时调试日志的格式
- 更新了内建的重起服务器(在 win32 体系中)
- 客户端关闭浏览器时,停止继续从文件句柄读取并输出数据流
- 增加了 $c->controller, $c->model 和 $c->view 快捷方式
- 改用 Text::SimpleTable.

如果你用 mod_perl 的话,需要更新为最新的 Catalyst::Engine::Apache (0.99002) 。

此外还需要安装以下模块

HTTP::Body 0.4
Text::SimpleTable
Tuesday, November 8th, 2005
12:27 pm
[chunzi]
Plugin: UploadProgress, JSAN, upcoming
看到 dev.catalyst.perl.org 中有两个新的 Plugin 。

Catalyst::Plugin::UploadProgress

上传文件还是和以前一样处理,在表单提交的时候,帮定一个 Ajax 请求,然后返回这个 Plugin 计算出来的上传进度。当然每次请求都有一个 upload_id ,通过它来识别相关的文件。返回的 view 是 c.progress 的相关数据,当然也可以根据这些数据自己作一个 bar 来展示(不断更新 bar 对象的宽度)。

Catalyst::Plugin::JSAN

刚认识了 JSAN 就看到了(其实就算之前看到也不会在意)。这个 Plugin 主要东西都在 Helper 里面。通过 script/myapp_create.pl JSAN 会在 script/ 下面生成一个 myapp_jsan.pl 的脚本。然后你可以通过这个脚本从 JSAN 上下载并安装到该项目的 [home]/root/static/js 目录中(如果环境变量 $ENV{JSAN_PREFIX} 没有设置的话)。
Friday, November 4th, 2005
8:51 am
[chunzi]
Catalyst 5.49_03 发布
离我们期望的稳定版本 5.5 越来越近了。

Changelog:

- 修复了 $c->req->{path} 的后向兼容性
- 可以在 ENV 中设定禁用 debug 输出
- 为 catalyst.pl 增加了 -scripts 选项,以便更新脚本代码
- 修改 helpers 代码,原来默认使用短名称 C ,现在默认使用长名称 Controller
- 增加了 Catalyst::Controller, Catalyst::Model 和 Catalyst::View 三个基类
- 增加了 JavaScript 调试屏幕 ,以便显示特定的代码 dump
- 增加了 _DISPATCH, _BEGIN, _AUTO, _ACTION 和 _END 动作
- 增加了多进程外部 FastCGI 支持 (参考 myapp_fastcgi.pl -help) (Sam Vilain)
- 在 HTTP 引擎内部的重新启动过程现在可以在父进程关闭时正常退出
- 改善了内部重起循环的性能
- 现在重起机制能够根据新加到系统应用中的文件(新增文件导致上级目录的 mtime 更新)触发工作
- 现在重起机制能够根据正常应对系统用到的模块的变化。
- 在 TestApp 内修复了内存溢出问题。

大多可见的变化如下:

1. 长类型 (Controller/Model/View) 为默认,短名称 (C/M/V) 仍然可用,不过需要加上 "-short" 参数:

    catalyst.pl -short MyApp
     script/myapp_create.pl -short controller Foo
     script/myapp_create.pl -short model Bar
     script/myapp_create.pl -short view Baz


2. Catalyst::Base 已经被分为多个更为简洁的基类

     package MyApp::Controller::Foo;
     use base 'Catalyst::Controller';
     1;

     package MyApp::Model::Bar;
     use base 'Catalyst::Model';
     1;

     package MyApp::View::Baz;
     use base 'Catalyst::View';
     1;


老的 Catalyst::Base 仍然可用,也没有计划在将来完全摒弃它。

3. 你现在可以只用一行命令来更新你的 helper 脚本

     catalyst.pl -nonew -scripts MyApp
Wednesday, November 2nd, 2005
11:28 am
[chunzi]
Catalyst::Model::SVN
刚刚从邮件列表看到的消息,现在有了一个 SVN 的 Model ,虽然目前仅仅是只读的列出仓库中的数据,不过以后将有可能(一定会)扩展为完整功能的 Model 。

这对我来说是激动人心的,之前一直在构思一个基于 svn 的协作翻译的平台,着实希望有一个集合可以让我在业务逻辑的思考下操作 svn 仓库。粗粗看了看 subversion 自带的 binding 中的 Perl 部分,对于 SVN::* 的那些模块,似乎很繁杂。能有这样一个 Model 无论如何都是一件值得高兴的事情。期待中。
Tuesday, November 1st, 2005
12:54 pm
[shijialee]
不爽
发泄一下 :)

sub do_edit : Local {
    my ( $self, $c, $id ) = @_;
    $c->form( optional => [ BookDB::M::BookDB::Book->columns ] );
    BookDB::M::BookDB::Book->retrieve($id)->update_from_form( $c->form );
    $c->forward('edit');
}


上面是 BookDB 里的一段程序,$c->form 调用 Catalyst::Plugin::FormValidator (是 Data::FormValidator 的一个外包),不过这段 code 里第二个 $c->form 的使用让我看着觉得不爽。 $c->form('....') 返回一个 Data::FormValidator object. Catalyst::Plugin::FormValidator 的 form 的代码如下

sub form {
    my $c = shift;
    if ( $_[0] ) {
        my $form = $_[1] ? {@_} : $_[0];
        $c->{form} =
          Data::FormValidator->check( $c->request->parameters, $form );
    }
    return $c->{form};
}


我如果自己写上面那段程序的话,就改为

    my $new_form = $c->form( optional => [ BookDB::M::BookDB::Book->columns ] );
    BookDB::M::BookDB::Book->retrieve($id)->update_from_form( $new_form );


更清楚点,不是么? 还是萝卜青菜各有所爱?

看 catalyst 时才意识到有太多的模块没用过。Class::DBI 和众多衍生的模块 , CatalystCatalyst::Plugin 里众多的缺省模块, TempalateToolkits, , sqlite ,Class::Data::Inheritable, Class::Accessor::Fast , NEXT 后面这三四个不是必须了解, 他们是用来搭成 Catalyst 这个框架的. 只不过是我刨根掘底连带着看了。=)

doc for Catalyst::Plugin::FormValidator http://xrl.us/h9tg
doc for Data::FormValidator http://xrl.us/h9th
Wednesday, October 26th, 2005
12:16 pm
[joe_jiang]
catalyst MVC
5.49_02 2005-10-26 12:39:00 
        - Whole new dispatcher! 崭新的派发器
        - Added index action 加入了索引动作
        - Added path_to method 加入了一个新方法
        - Added support for passing an IO::Handle object to $c->res->body. 允许给应答一个 IO::Handle 对象作为参数
          (Andrew Bramble)
        - Added a new welcome screen. 一个新的默认欢迎页面
        - Included Catalyst buttons and icons in helper. 在 helper 模块里面引入了按钮和图标
        - Added Static::Simple plugin to core. 在核心里面加入 Static::Simple 插件
        - Added self restarting test server 加入一个自动重启的测试服务器
        - Added filename to debug output for uploaded files. 上传文件时候自动在 debug 里面输出文件名
        - Fixed forwarding with embedded arguments. 修正了带有内嵌参数的 forward 动作
        - Fixed handling of escaped query strings. 修正了对于跳出查询串的处理
        - Added upload parameters back into $c->req->params. 重新使用请求的参数来存放上传参数
        - Added multiple paths support to dispatcher 给派发器加入多路支持
        - Fixed bug in req->path where changing the path added a trailing slash.
        - Removed req->handle and res->handle 拿掉了请求和回应的 handle
        - Added prepare_body_chunk method as a hook for upload progress. 加入一个上传进度的钩子
        - Fixed bug in uri_for method when base has no path. 修正了 uri_for 方法没有路径时候的一个 bug
        - Added automated tests for HTTP, CGI, and FastCGI servers. 给 HTTP、CGI、FastCGI 服务器提供了自动测试

那么 catalyst 这个词的原来的意思是什么呢? dict catalyst:

"The Collaborative International Dictionary of English v.0.48"
catalyst \catalyst\ n.    1. (Chem.) a substance that initiates or accelerates a       chemical reaction without itself being affected; as,       thousands of enzymes serve in concert as calaysts to       produce the sequence of reactions we call "life"; the       industrial production of cheap ammonia depended on finding       a good catalyst.       [WordNet 1.5]    2. something that serves as a precipitating occasion for an       event; as, the invasion acted as a catalyst to unite the       country.    Note: A catalyst is never the main cause of an event, but may          serve to hasten events for which the underlying causes          are present prior to the appearance or occurrence of          the catalyst.          [WordNet 1.5 +PJC]    3. something or someone that causes events to happen with       itself being changed.       [PJC]
"WordNet (r) 2.0"
catalyst      n 1: (chemistry) a substance that initiates or accelerates a           chemical reaction without itself being affected [syn: accelerator]           [ant: anticatalyst]      2: something that causes an important event to happen; "the         invasion acted as a catalyst to unite the country"
"Moby Thesaurus II by Grady Ward, 1.0"
75 Moby Thesaurus words for "catalyst":    agent, agent provocateur, agitator, agitprop, alterant, alterative,    alterer, author, begetter, beginner, catalysis, catalytic agent,    causer, creator, decay, demagogue, dialysis, dissociation,    effector, engenderer, exciter, father, ferment, firebrand, fission,    fomenter, generator, goad, hydrolysis, hydrolyst, impetus, impulse,    incendiary, incentive, incitation, incitement, inciter, inflamer,    innovationist, innovator, inspirer, instigator, introducer, leaven,    maker, mischief-maker, modificator, modifier, mother, motivation,    mover, originator, parent, photolysis, precursor, prime mover,    primum mobile, producer, provocateur, provoker, rabble-rouser,    ringleader, rouser, seditionary, seditionist, sire, splitting,    spur, stimulant, thermolysis, transformer, transmogrifier,    troublemaker, urger, yeast
Tuesday, October 25th, 2005
4:48 pm
[shijialee]
DefaultEnd plugin 帮你做模板处理
正在看 catalyst 上的 BookDB 源代码。里面的 Controller
程序 BookDB/lib/BookDB/C/Book.pm 有这么一段:

sub list : Local {
my ( $self, $c ) = @_;
$c->stash->{template} = 'Book/list.tt';
}

但如果你读了文档 Catalyst 介绍 http://xrl.us/h2mt 就会看到
[quote start]
sub hello : Global {
my ( $self, $c ) = @_;
$c->stash->{template} = 'hello.tt';
}

sub end : Private {
my ( $self, $c ) = @_;
$c->forward('MyApp::V::TT');
}

通常总是在请求的末尾来套用模板,因此使用全局的 end 动作来完成是最好的。[quote end]

上面是在说因为 end : Private 是在一个request和所有已定义的 action 不相符时最后调用的,所以 template 一般放在 end 里用来处理模板。

但 Book.pm 里没有 end : Private ,那么模板是怎么处理的? 到 irc.perl.org 里的 #catalyst 问了以下。说是使用了 Catalyst::Plugin::DefaultEnd ,帮你做了 end 里的 forward 那一步。
看了一下 BookDB/lib/Book.pm ,里面有这一行
use Catalyst qw/-Debug FormValidator FillInForm DefaultEnd Static::Simple/;

okay!! 那这就意味着我们可以省掉声明自己的 end : Private 方法来处理模板了。
DefaultEnd 的文档
http://search.cpan.org/~mramberg/Catalyst-Plugin-DefaultEnd-0.03/lib/Catalyst/Plugin/DefaultEnd.pm
9:43 am
[chunzi]
Catalyst-Plugin-HTML-Scrubber-0.01
Catalyst 下面的 Plugin 总是那么简单。这个 Plugin 目标要对来自请求的所有参数进行 html 安全过滤或者代码清理。核心过滤使用了 HTML::Scrubber 模块,所以相关的 Plugin 配置也是迎合 HTML::Scrubber 的需要。

所谓安全,就是去掉 Javascript 代码,所谓干净,就是去掉 html 注释,并且仅仅允许使用若干指定的 html 标签。如果我们要做 CMS 并提供用户编辑 html 源文件的话,这个 Plugin 可以帮助我们简化安全过滤。只是它针对所有的请求参数,也就是 $c->req->params 都进行了这样的过滤,是不是会发生聪明人自作聪明多干活的事情呢?我宁愿在指定的参数上作这样的过滤。或许该模块作者要做的项目确保不会出现干扰问题,所以才写了这样的 Plugin 吧。
Monday, October 24th, 2005
9:04 pm
[fayland]
Template Toolkit 的配置选项
Cross-Post @ http://www.fayland.org/journal/Template_Configuration.html

今天用 Catalyst 写一个 RSS 聚合器程序的时候,发现 TT 的配置总是出错。后来才发现原来是配置选项出了点问题。

原来的代码差不多是这样子的:

package Feeder::V::TT;

use strict;
use base 'Catalyst::View::TT';
use Template::Constants qw( :debug );

__PACKAGE__->config({
   # any TT configurations items go here
   INCLUDE_PATH => Feeder->config->{'home'} . '/templates/',
   POST_CHOMP => 1,
   PRE_CHOMP => 1,
   EVAL_PERL => 1,
   PRE_PROCESS => 'header.tt',
   POST_PROCESS => 'footer.tt',
   DEBUG => DEBUG_PARSER | DEBUG_PROVIDER,
   CONTEXT => undef,

   # two optional config items
   CATALYST_VAR => 'Catalyst',
   TIMER => 1,
});

可怎么运行都不行。试了好一会儿,后来才发现原来 Template 的 INCLUDE_PATH 默认是用 : 来分隔多个路径的,比如:

INCLUDE_PATH => '/home/abw/templates:/usr/share/templates',

这样就是两个路径。而我运行在 Win32 下,发现 Template 将 E:/Fayland/Feeder/templates 划分为了两个路径 E 和 /Fayland/Feeder/templates, 所以运行程序总是跳出找不到模版文件。知道原因后查了查 Perl Template Toolkit 一书,在配置里加了一句:
DELIMITER    => ';',

这样就不是用 : 而是用 ; 来划分了。

这只是因为自己不熟悉 Template 的配置选项。于是就复习了一遍,将常用的几个翻译如下:

ABSOLUTE

指出用绝对路径的文件是否被解析。默认为 0.
如 /foo/bar 在 1 时为绝对路径而在 0 时为相对路径。
在 0 时使用类如 [% INSERT /etc/passwd %] 会出错,除非相对路径也有这文件。

ANYCASE

指示性关键字如 INCLUDE 是否允许小写

BLOCKS

此选项用于预先定义一系列模版块。
my $tt = Template->new({
BLOCKS => {
header => 'The Header. [% title %]',
footer => sub { return $some_output_text },
another => Template::Document->new({ ... }),
},
});

Hash 的值可以是模版内容,子程序或是 Template::Document
这样我们就可以在其他模版文件里调用它们。

COMPILE_DIR/COMPILE_EXT

Template 可以将模版文件编译成 Perl 文件保存以便接下来的再次调用。
my $tt1 = Template->new({
COMPILE_DIR => '/tmp/ttc',
COMPILE_EXT => '.ttc1',
});

COMPILE_DIR 是地址,COMPILE_EXT 为后缀名。

DELIMITER

这就是我所碰到的问题解决方案。解释见最前面。
# Win32 only
my $tt = Template->new({
DELIMITER => ';',
INCLUDE_PATH => 'C:/TT2/Templates;D:/My Templates',
});

CONSTANTS

编译时编译一次这些常量,而不是每次运行都编译一次。这样能稍微提高点速度。
my $tt = Template->new({
CONSTANTS => {
title => 'A Demo Page',
author => 'Joe Random Hacker',
version => 3.14,
},
};

CONSTANT_NAMESPACE

所有定义的 CONSTANTS 默认用 [% constants.title %] 来获得。而 CONSTANT_NAMESPACE 用来改变前缀。如:
CONSTANTS_NAMESPACE => 'const',

后,可以用 [% const.title %] 来访问。

NAMESPACE

用来定义多个 CONSTANT_NAMESPACE
my $tt = Template->new({
NAMESPACE => {
site => Template:::Namespace::Constants->new({
title => "Wardley's Widgets",
version => 2.718,
}),

author => Template:::Namespace::Constants->new({
name => 'Andy Wardley',
email => 'abw@andywardley.com',
}),
},
};


这样你就可以分别用 [% site.title %] 和 [% author.name %] 访问不同的常量。

CONTEXT

设置上下文。具体用途有点复杂。略过。

DEBUG

设置哪些地方需要调式。所定义的常量位于 use Template::Constants qw( :debug );
有两种写法:
DEBUG => DEBUG_PARSER | DEBUG_PROVIDER,
# or
DEBUG => 'parser, provider',

具体哪个啥意思查手册。

DEFAULT

当在 INCLUDE_PATH 里找不到模版文件时,默认调用该文件
my $tt = Template->new({
DEFAULT => 'notfound.html',
});

ERROR/ERRORS

定义一些常用的 错误 模版,然后在必要时调用它们。
my $tt = Template->new({
ERROR => {
'user.login' => 'user/login.html',
'user.passwd' => 'user/badpasswd.html',
'user' => 'user/index.html',
'default' => 'error/default',
},
});

必要时通过 [% THROW user.login 'no user id: please login' %] 来调用。
或在当前的 Template::Context 调用: $context->throw('user.passwd', 'Incorrect Password');
或在 Perl 代码中调用: die (Template::Exception->new('user.denied', 'Invalid User ID'));

EVAL_PERL

确定类如 PERL 或 RAWPERL 这样的块是否被执行。默认为 0

FILTERS

自定义自己的 filter, 过滤器。用于处理文件的某一些转换。 Template 默认自带了一些。
$tt = Template->new({
FILTERS => {
'sfilt1' => \&static_filter, # static
'sfilt2' => [ \&static_filter, 0 ], # same as above
'dfilt1' => [ \&dynamic_filter_factory, 1 ],
},
});

而后调用
[% FILTER sfilt1 %]
Blah blah blah.
[% END %]

INCLUDE_PATH

这个前面用了 n 多次了。它就是用于指定你要搜索的模版文件的文件夹。这几乎是用得最多的一个指令。

START_TAG/END_TAG

用以指定 template 指令的起始和终止符号。默认为 %
my $tt = Template->new({ 
START_TAG => quotemeta('<+'),
END_TAG => quotemeta('+>'),
});

这样就用 <+ INCLUDE foobar +> 而不是 [% %] 来调用指令了。

INTERPOLATE

内插。默认为 0
# INTERPOLATE => 0
<a href="http://[% server %]/[% help %]">
<img src="[% images %]/help.gif"></a>
[% myorg.name %]

# INTERPOLATE => 1
<a href="http://$server/$help">
<img src="$images/help.gif"></a>
$myorg.name
# explicit scoping with { }
<img src="$images/${icon.next}.gif">

OUTPUT/OUTPUT_PATH

这个我在老版本的 Eplanet 里是常用的。可以将内容输出到文件。

PRE_CHOMP, POST_CHOMP

是否在 [% %] 指令前后去除空行。默认不去除。这样的话:
<a href='[% address %]'>Click Here</a>

的话产生的最后结果可能是:
<a href='
fayland.html
'>Click Here</a>

我喜欢将它们设置成 1, 即使有时候应该分开的行也并起来了。

PRE_DEFINE, VARIABLES

这两个选项是一样的。用于设置一些默认值。如果 STASH 没有设置的话采用它们,设定的话忽略。
my $tt = Template->new({
PRE_DEFINE => {
title => 'A Demo Page',
author => 'Joe Random Hacker',
version => 3.14,
},
};

PRE_PROCESS, POST_PROCESS

调用一个 process 模版文件时预先调用和后来调用的模版文件。一般用于放置头文件和尾文件。
my $tt = Template->new({
PRE_PROCESS => [ 'config', 'header' ],
POST_PROCESS => 'footer',
};

STASH, process

这些在 Catalyst 没用到所以也不介绍了。

Enjoy!

Share me what u think.
Saturday, October 22nd, 2005
9:56 am
[chunzi]
Catalyst::View::TT 更新到 0.14
这次更新除了 fix 一些 bug 之外,还提供一些新的特性,所以有必要了解一下。

原来默认使用 Template::Timer 来统计每个模版段落处理所消耗的时间,现在即便在 debug 模式下也不会启用该功能,除非在配置中指定:

MyApp->config({
'MyApp::V::TT' => {
TIMER => 1,
},
});

原来模版文件是放在 root 目录下面的,现在不这样做了。原先我就奇怪,root 下面基本上都是 public 的东西,为何 template 也放在其中,所以我自己写的时候都在自己的 view 里面定义好 INCLUDE_PATH 的,不过现在好了,直接在外面写好配置:

our $ROOT = '/home/dent/catalyst/MyApp';

MyApp->config({
name => 'MyApp',
root => $ROOT,
'MyApp::V::TT' => {
INCLUDE_PATH => ["$ROOT/templates/src", "$ROOT/templates/lib"],
PRE_PROCESS => 'config/main',
WRAPPER => 'site/wrapper',
},
});
Thursday, October 20th, 2005
3:42 pm
[shijialee]
使用 svk & catalyst
用来把 dev.catalyst.perl.org 上的原代码 / 例子下载.

我用的是 debian unstable. 其他的 OS 请看 svk 的安装文档 http://svk.elixus.org
svk 中文教程文档: http://svk.elixus.org/?ZHSVKTutorial

提供一个简单的步骤:

# debian 专用,woody 不同,
apt-get install svk

# 初始化 svk 缺省 repository , 在 ~/.svk/local.
svk depotmap --init

# 把 Catalys BookDb 的例子下载下来
svk mirror http://dev.catalyst.perl.org/repos/Catalyst/trunk/examples/BookDB //catalyst/BookDB
svk sync //catalyst/BookDB

# 把 BookDB 复制到当前工作目录里的BookDB下,现在就可以随便修改这个目录的文件了
svk co //catalyst/BookDB BookDB
10:20 am
[chunzi]
Catalyst::Plugin::StashSetter
又冒出来一个 Plugin ,比较简单,目标是一次对多个传入 stash 的参数使用键值对的形式赋值。

原来这样写,比较罗索,

$c->stash->{param1} = 'value1';
$c->stash->{param2} = 'value2';
$c->stash->{param3} = 'value3';

现在可以简单点:

$c->set_stash( param => 'value' );
$c->set_stash(
param1 => 'value1',
param2 => 'value2',
param3 => 'value3',
);
[ << Previous 20 ]
About LiveJournal.com