Dancer圣临历中介绍了一个新插件Dancer::Plugin::SimpleCRUD。可以很快的生成对数据库表的create/read/update/delete。大概阅读了一下代码。主要就是使用HTML::FromDatabase模块生成read的页面,用CGI::FormBuilder模块生成create/update/delete的页面,用Dancer::Plugin::Database::Handle模块操作数据库。因为是Simple,所以html代码都是固定的,不甚美观。但是思路可以学习,通过这两个模块,可以自己结合Dancer的template系统做CRUD了。 先来说HTML::FromDatabase模块,这个只涉及select,所以特别简单:

any ['get', 'post'] => '/add/:element' => sub {
    my $element = params->{'element'};
    if ( request->method eq 'GET' ) {
        my $sth = database->prepare("select * from $element");
        $sth->execute();
        my $table = HTML::Table::FromDatabase->new( -sth => $sth )->getTable;
        template 'info', { table => $table };
    };
...
};

这样就可以了,getTable方法的返回是一个字符串(内容就是table/tr/td代码),直接传递给tmpl就行了~~ 然后看CGI::FromBuilder模块:

any ['get', 'post'] => '/add/:element' => sub {
    my $element = params->{'element'};
    my $paramsobj = request->method eq 'POST' ? { params => { params() } } : undef;
    my @fields;
    if ( $element eq 'food' ) {
        @fields = qw/fid name shelf/;
    } elsif ( $element eq 'market' ) {
        @fields = qw/mid name location/;
    } elsif $element eq 'price' ) {
        @fields = qw/fid mid price time/;
    } else {
        return "Error element";
    };
    my $form = CGI::FormBuilder->new(
        params => $paramsobj,
        fields => \@fields,
    );

    my $sth = database->prepare("select * from $element order by fid desc");
    $sth->execute;
    my $default_hashref = $sth->fetchrow_hashref;
    my $action = $default_hashref ? 'update' : 'insert';
    if ( request->method eq 'POST' && $form->submitted && $form->validate ) {
        my $success = database->quick_update("$element", {name => params->{'name'}}, {shelf => params->{'shelf'} });
        redirect "/add/$element" if $success;
        return "update error";
    } else {
#        return $form->render(values => $default_hashref,
        my $hash = $form->prepare(values => $default_hashref,
                             title  => $element,
                             action => "/add/$element",
                             method => "post",
                            );
        template 'crud', { hash => $hash, };
    };
};

这里的关键,就是$paramsobj变量。否则无法区分GET和POST的。 和HTML::FromDatabase一样,有个render()直接返回内容是组装好的html代码的字符串;另外,CGI::FormBuilder模块还提供一个prepare()方法,返回的是hash——因为render()返回的html代码是完整的html/head/body…(事实上CGI::FormBuilder模块的构造器还提供指定js函数和css格式的参数);所以如果要加进template里,可以把prepare()返回的hash传递给tmpl去操作! 然后还发现一个小问题,如果table里一条数据都没有,fields为undef,模块运行有问题的…… 最后,quick_update()是Dancer::Plugin::Database::Handle模块里提供的,这个模块里提供了一系列_quick*()方法,用来快速操作数据库。