他にも user_id なんかのカラムは複数のテーブルへカラム定義するケースが多いでしょう。特に正規化などをちゃんとするほど。
個人的な小さいアプリケーションや、開発のごく初期ではカラム定義の内容を細かく変えるケースがあるんじゃないかと思います。
そういう時は Schema Loader を使ったり ALTER TABLE しまくったり(もしくは DROP TABLE & CREATE TABLE)することでしょう。
まぁ、それでいいんですけど、開発の初期なんかは DROP TABLE & CREATE TABLE してた方が手っ取り早かったりすると思います。
で、この DROP TABLE & CREATE TABLE しまくりの時に SQL で CREATE TABLE 文を書く、そして前述のいろんなテーブルで使われるような user_id の定義を変える。
といったときに Column Sugar で設定したカラム定義を一箇所書き換えるだけで済むので定義の変更漏れとかがなくなるというマニアックのシチュエーションがあります。
その他には、前述の通りにたような役割のカラムを一回だけ定義しておけば、テーブルのカラム定義では定義名を指定するだけで使いまわせるので楽になります。
たとえば Inflate の設定やら Default 値を CODE リファレンスで作ってるようなカラム定義で楽ができますよ。
さて、さっそくここで Column Sugar の定義でもしてみようと思います。
主に user テーブルの id カラムを作る人向けの定義は以下のようになります。
column_sugar 'user.id'
=> int => {
required => 1,
unsigned => 1,
};
普通のカラム定義の column の使い方とほとんど同じです。
column の代わりに column_sugar を使います。また、 column は install_model $tablename => {}; の中でしか利用できませんが、 column_sugar はどこで書いても OK です。
第一引数が "テーブル名.カラム名" という感じで、テーブル名とカラム名を . でつなげた形で指定します。
第二引数はカラム型。
第三引数がカラムの詳細な定義となります。
二と三は column と同じです。
重要なのが第一引数で "user.id" と定義した Column Sugar は、 user テーブルのカラム定義の中で使うと id というカラム名になり、 bookmark テーブルの中のカラム定義で使うと user_id というカラム名になります。
実際先程の column_sugar の定義を使ってみましょう。
install_model user => schema {
key 'id';
unique 'nickname';
column 'user.id';
columns qw/ nickname /;
};
install_model bookmark => schema {
key [qw/ url_id user_id /];
index 'user_id';
column url_id => int => {};
column 'user.id';
};
このような定義をすると以下のような CREATE TABLE 文に対応します。
CREATE TABLE user (
id INT UNSIGNED NOT NULL,
nickname CHAR(255) ,
PRIMARY KEY (id),
UNIQUE (nickname)
);
CREATE TABLE bookmark (
url_id INT ,
user_id INT UNSIGNED NOT NULL,
create_at INT UNSIGNED NOT NULL,
PRIMARY KEY (url_id, user_id)
);
CREATE INDEX user_id ON bookmark (user_id);
user.id は user テーブルの中だと user の部分を省略して id というカラム名になって、 user テーブル以外だと user_ の prefix がついて user_id というカラム名になってることがわかると思います。
さて、カラム定義の使い回しがし易いという column_sugar なんですが、定義を流用したいけども部分的に定義を変更したいケースがあると思います。例えば auto_increment をつけるとか。
そういった差分で上書きしたいときもちゃんと上書きして設定する事ができます。
例えば以下のようにcolumn_sugar の定義つけた unsigned => 1 を無効化したいときに以下のようかけます。
install_model user => schema {
key 'id';
unique 'nickname';
column 'user.id' => {
unsigned => 0
};
columns qw/ nickname /;
};
これは下記の SQL になります。
CREATE TABLE user (
id INT NOT NULL,
nickname CHAR(255) ,
PRIMARY KEY (id),
UNIQUE (nickname)
);
先程あった、 UNSIGNED の属性が消えてるのがわかると思います。
今度は、属性を追加したいときは単純に追加するだけです。
install_model user => schema {
key 'id';
unique 'nickname';
column 'user.id' => {
auto_increment => 1,
};
columns qw/ nickname /;
};
このように auto_increment 属性を追加した場合は
CREATE TABLE user (
id INTEGER NOT NULL PRIMARY KEY,
nickname CHAR(255) ,
UNIQUE (nickname)
);
以上のように PRIMARY KEY 属性が追加されました。
さて、今度はカラム名だけを変えたいという時もあるでしょう。
そういう時は、以下のように定義すると名前だけかえられます。
# global.epoch という定義
column_sugar 'global.epoch'
=> int => {
required => 1,
unsigned => 1,
};
install_model bookmark => schema {
key [qw/ url_id user_id /];
index 'user_id';
column url_id => int => {};
column 'user.id';
# create_at を生の値でも使いたい
column 'global.epoch' => 'create_at';
};
単純に、 column の第二引数に書き換えたいカラム名を指定するだけですみます。
上記の定義は下記の CREATE TABLE になります。
CREATE TABLE bookmark (
url_id INT ,
user_id INT UNSIGNED NOT NULL,
create_at INT UNSIGNED NOT NULL,
PRIMARY KEY (url_id, user_id)
);
じゃぁ名前変更と属性変更を同時にしたい場合はどうするか!?という時は、単純に書き換えたカラム名の次の引数に差し替えたい属性の HASH リファレンスを書けばいいだけです。
install_model bookmark => schema {
key [qw/ url_id user_id /];
index 'user_id';
column url_id => int => {};
column 'user.id';
# create_at を生の値でも使いたい
column 'global.epoch' => 'create_at';
default => sub { time() },
};
};
今日は Data::Model らしい Column Sugar に関して紹介しました。変に長文になってしまってあれですけど、明日は今日の続きを書きたいなとおもいます。