DBIx::Class::FromSledgeやってみました。

DBICやらねばやらねばと思っていたところで、DBIx::Class::FromSledgeというモジュールがリリースされたとの事で折角なのでDBICも合わせてやってみました。

DBIx::Class::FromSledgeは、create_from_sledge、update_from_sledgeの二つのメソッドが有り、この人達にPagesオブジェクトを投げると良い感じにinsert,updateしてくれます。

配置

`-- SampleApp
    |-- Config
    |   |-- _common.pm
    |   `-- _test.pm
    |-- Config.pm
    |-- DB
    |   `-- Table01.pm
    |-- DB.pm
    |-- Pages
    |   `-- Root.pm
    `-- Pages.pm

DB.pmがスキーマで、DB/Table01.pmがテーブルのクラスです。

まずこれら2つの中身を。

DB.pm

package SampleApp::DB;
 
use base qw(DBIx::Class::Schema);
 
use SampleApp::Config;
 
__PACKAGE__->connection(SampleApp::Config->instance->datasource);
__PACKAGE__->load_components(qw(FromSledge));
__PACKAGE__->load_classes(qw(Table01));

1;

DB/Table01.pm

package SampleApp::DB::Table01;
 
use strict;
 
use base qw(DBIx::Class);
 
__PACKAGE__->load_components(qw(
    FromSledge
    PK::Auto
    Core
));
 
__PACKAGE__->table('table01');
__PACKAGE__->add_columns(qw(id name registed timestamp));
__PACKAGE__->set_primary_key('id');
 
1;

Schemaという概念がCDBIとかなり違いますでしょうか。

load_componentsにそれぞれFromSledgeを足し込んでます。

ちなみにtable01の構造
table01

mysql> desc table01;
+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id        | int(10) unsigned |      | PRI | NULL    | auto_increment |
| name      | varchar(255)     | YES  |     | NULL    |                |
| registed  | datetime         | YES  |     | NULL    |                |
| timestamp | timestamp(14)    | YES  |     | NULL    |                |
+-----------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

以上で準備が出来ましたので、insert・updateするPagesを作りました。

$self->modelにスキーマをsetしてます。

Pages/Root.pm

package SampleApp::Pages::Root;
 
use strict;
 
use base qw(SampleApp::Pages);
 
use Sledge::Plugin::Validator;
 
use SampleApp::DB;
use Time::Piece::MySQL;
use Data::Dumper;
 
__PACKAGE__->mk_accessors(qw(model));
 
__PACKAGE__->register_hook(
    BEFORE_DISPATCH => sub {
        my ($self) = @_;
        $self->model(SampleApp::DB->connect);
    },
);
 
sub now { Time::Piece->new->mysql_datetime }

そして、いよいよ登録・更新するメソッドです。

まずバリデートメソッド

sub valid_index {
    my ($self) = @_;
    return unless $self->is_post_request;
    $self->valid->err_template('index');
    $self->valid->check(
        name => [qw(NOT_NULL), [qw(LENGTH 1 255)]],
    );
}

DBIC::FromSledgeの方ではValidatorオブジェクトからカラムを決定するようです。

$page->valid->{PLAN}->{$col}

つまりvalidation対象のカラムがPagesから引っこ抜かれると。なるほど。


そして、バリデートをめでたく抜けて、insert or update。

sub dispatch_index {
    my ($self) = @_;
    if ($self->is_post_request) {
        if (my $id = $self->r->param('id')) {
            $self->model->resultset('Table01')->find($id)->update_from_sledge($self);
        } else {
            $self->model->create_from_sledge('Table01', $self, {registed => now});
        }
    } else {
        if (my $id = $self->r->param('id')) {
            $self->tmpl->param(obj => $self->model->resultset('Table01')->find($id));
        }
    }
 
    my $itr = $self->model->resultset('Table01')->search({});
    $self->tmpl->param(table01 => $itr);
}

1;

create_from_sledge時は決め打ちでregistedにnowを指定してます。


実行後

mysql> select * from table01;
+----+------------------+---------------------+----------------+
| id | name             | registed            | timestamp      |
+----+------------------+---------------------+----------------+
|  1 | ネプチューンマン | 2007-01-11 16:52:00 | 20070111171405 |
|  2 | 喧嘩マン         | 2007-01-11 17:11:02 | 20070111171102 |
+----+------------------+---------------------+----------------+

無事入りました!


未使用時との比較
例ではテーブルのカラムが少ないのであまりよしくないですが、従来と比較するとかなりすっきりしそうです。

※valid_xxxは前提で。

従来

Table->create({
    mail => $self->r->param('mail'),
    tel => $self->r->param('tel'),
    fax => $self->r->param('fax'),
    zip => $self->r->param('zip'),
    stat => 1,
    registed => Time::Piece->new->mysql_datetime,
);

という感じで書いていましたが、
FromSledge

$schema->create_from_sledge('Table', $self, {stat => 1, registed => Time::Piece->new->mysql_datetime});

すっきり!!