DBIx::Skinny::Schema::Loaderで楽々Schema設定 #23B!

nekokakさんと名前が紛らわしいと評判のnekoyaです。

今日はSkinny本体ではなく、関連モジュールとしてDBIx::Skinny::Schema::Loaderを紹介します。

インストールは、ふつうにCPANから

cpan DBIx::Skinny::Schema::Loader

するか、githubからcloneしてください。

DBIx::Skinny本体のバージョンが古いと動きません。CPANから0.05を入れるか、あるいはgithubの最新版を入れてください。

DBIx::Skinny::Schema::Loaderは名前から想像できるように、Skinnyで使用するSchemaを自動設定するモジュールです。

その場でinstall_tableを実行する動的生成の他に、Schemaクラスのファイルを書き出す静的生成にも対応しています。

対応DBはSQLite, MySQL, Postgresqlです。Skinny本体はOracleにも対応していますが、Schema::Loaderでは今のところサポートしていません。

■動的生成

Schemaクラスを以下のように書くと、ロード時にDBに合わせたSchema情報を設定します。

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

__PACKAGE__->load_schema;

1;

通常、Schemaクラスでは use DBIx::Skinny::Schema; しますが、Schema::Loaderを使う場合はuse baseしてください。

load_schemaを呼ぶと、DBの中を見て、各テーブルのpkとcolumnsを設定するinstall_tableが実行されます。

それ以外の要素、例えばinflate/deflateやtriggerなどを設定したい場合は、

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

install_table users => schema {
    trigger pre_insert => sub {
        my ($class, $args) = @_;
        $args->{ status } = 'hooked';
    };
};

__PACKAGE__->load_schema;

1;

のように書きます。install_tableは複数回に分けて書いてもいいので、ここに書いたtriggerとload_schemaが設定するpk, columnsの両方の設定が生きます。

load_schemaによる動的生成を使う場合の注意点として、Skinnyクラス(上の例だとYour::DB)にuse DBIx::Skinny setupでDBの接続情報を書いておくことが必要です。

newで接続情報を渡したりする場合でもやってやれなくはないのですが、無理矢理感があるので、そういったケースでは基本的には次の静的生成をお勧めしています。

■静的生成

まず、以下のようなスクリプトを書きます。publish_schema.plなど適当な名前で保存しておきましょう。

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

そして、以下のようにすると、Your::DB::Schemaのファイルが書き出されます。

perl publich_schema.pl > lib/You/DB/Schema.pm

DBICと違ってSkinnyのSchemaは1ファイルで完結するので、直接ファイルを書き出すのではなく、標準出力に吐き出すようにしています。

make_schema_atは第2引数にオプションを指定して、出力するSchemaクラスのカスタマイズが出来ます。

例えば、先程のload_schemaのようなtrigger設定を入れるには以下のようにします。

use DBIx::Skinny::Schema::Loader qw/make_schema_at/;

my $before = << '...';
install_table users => schema {
    trigger pre_insert => sub {
        my ($class, $args) = @_;
        $args->{ status } = 'hooked';
    };
};
...

print make_schema_at(
  'Your::DB::Schema',
  {
    before_template => $before,
  },
  [ 'dbi:SQLite:test.db', '', '' ]
);

この他、install_tableブロックの後に指定の文字列を挿入するafter_templateや、install_tableブロックに任意のテンプレートを使用するtable_templateといったオプションがあります。詳細はPODをご覧ください。

PODには他にも動作の詳細やちょっとしたTipsを書いていますので、よかったら目を通してみてください(破滅的な英語ですが)。

このように、Schema::Loaderを使うとSchema定義を書く手間を軽減することが出来ます。個人的には、テーブル設計が流動的な開発初期はload_schemaによる動的生成を使い、ある程度落ち着いてきたらmake_schema_atによる静的生成に切り替えるといいんじゃないかと思ってます。

明日はDBIx::Skinny::InflateColumn::DateTimeを紹介します。

have a nice skinny days!:)