DBIx::Skinny::Schema::Loaderをgithubに上げました

(10/07追記)Skinny界のpgsql番長、id:sfujiwaraさんから早速PostgreSQL対応パッチを頂きました。すばらしす

DBIx::Skinnyを使うのに、install_table書くのが面倒なので作りました。

使い方とかはPodに書いてあるんだけど、改めて日本語で補足も交えて書いておきます。

package MyApp::DB::Schema;
use base qw/DBIx::Skinny::Schema::Loader/;

__PACKAGE__->load_schema;

1;

とか書いておくと、全テーブルのinstall_tableを自動設定します。

この時、DBから情報を読み出すのに、MyApp::DBに書いてあるdsnの設定を取ってくるのですが、これを正常動作させるには、今日(10/06)githubに上げた最新版のDBIx::Skinnyをインストールする必要があります。それ以前のバージョンでは動作しませんので注意してください。

load_schemaを実行すると、

install_table books => schema {
    pk 'id';
    columns qw/id author_id name/;
};

のように書いたのと同じように、pkとcolumnsをDBの内容に沿って自動で設定します。


他の設定を入れたい場合は、

package MyApp::DB::Schema;
use base qw/DBIx::Skinny::Schema::Loader/;

use DBIx::Skinny::Schema;  # import schema functions

install_utf8_columns qw/title content/;

install_table books => schema {
  trigger pre_insert => sub {
    my ($class, $args) = @_;
    $args->{ created_at } ||= DateTime->now;
  };
};

__PACKAGE__->load_schema;

1;

のように書きます。

この例では、install_tableでbooksにtriggerのみ設定しています。load_schemaを実行すると、別途pkとcolumnsがセットされます。DBIx::Skinnyでは一度のinstall_tableで全ての設定を書かなくても、何度も同じテーブルに対してinstall_tableを実行することが出来るので、このような書き方も問題ありません。

注意点としては、load_schemaだけの時は必要なかった「use DBIx::Skinny::Schema」を書く必要があるところです。DBIx::Skinny::Schemaはimport()実行時にcallerのシンボルテーブルを操作しますが、DBIx::Skinny::Schema::Loaderの中でこいつをuseしただけでは、MyApp::DB::Schemaには必要なメソッドが取り込まれないため、改めてDBIx::Skinny::Schema->importを実行する必要があります。

useする代わりに「BEGIN { DBIx::Skinny::Schema->import }」としても動作します(Schema::Loaderがrequireするため)が、サンプルでは記述が短い方を載せています。

このあたりの問題は、

などで詳しく説明されています。DBIx::Skinny::Schemaでは単純なメソッドのexportだけでなく他の処理も入っているので、このあたりを一発でうまくやる方法が思い付きませんでした。「use DBIx::Skinny::Schema」を書かずに動けばいいんですが、そのへんは今後の課題です。


静的なクラスファイルの書き出しは、

use DBIx::Skinny::Schema::Loader qw/make_schema_at/;
print make_schema_at(
    'Your::DB::Schema',
    {
        # options here
    },
    [ 'dbi:SQLite:test.db', '', '' ]
);

みたいなのをpublish_schema.plとかで保存して、

$ perl publish_schema.pl > Your/DB/Schema.pm

のようにすれば出来ます。

make_schema_atのオプションは今のところtemplateだけで、

print make_schema_at(
    'Your::DB::Schema',
    {
        template => 'install_utf8_columns qw/title content/;',
    },
    [ 'dbi:SQLite:test.db', '', '' ]
);

のように指定すると、install_tableの前にtempalteで指定した内容が出力されます。


なお、DBIx::Skinnyは先日PostgreSQLにも対応しましたが、このDBIx::Skinny::Schema::Loaderは残念ながら未対応です。実装は簡単だと思うんですが、手元にPostgreSQLの動く環境がないので書いてません。自分では使わないので、今のところ、そのうち気が向いたら対応するかも程度の扱いです。(10/07対応しました。id:sfujiwara++)

まだ自分でもほとんど使ってないので、人柱版としてどうぞ。