Alloyでのmigrationについて調べてみた

Titanium mobileでAlloyを使ってiOSアプリの開発しています。
既存のモデルに属性を追加しようとしてちょこっと嵌ったのでメモ。

マイグレーションについての公式ドキュメントはこちら。
Titanium 3.X - Appcelerator Docs

まず、app/migrations下にマイグレーション処理を記述したファイルを作成します。
ファイル名にはルール(※重要)があり、"YYYYMMDDHHmmss_モデル名.js"とします。(例:20120610049877_book.js)
そしてこのファイルに次のように2つメソッドを定義します。

migration.up = function(migrator) {
  // ここにDB更新の処理を記述
};

migration.down = function(migrator) {
  // ここにDBロールバックの処理を記述
};

モデルに属性を追加する場合はmigration.upにDBテーブルを拡張する処理を書けば良かったんだけど、そこでいろいろトラブル。migration.upが呼ばれたり呼ばれなかったり、DBのカラム追加処理がエラーになったり。

調べた結果、次のようなことがわかりました。

  • migrations下にファイルがあると、アプリ起動時ではなく、DBアクセスのあったタイミングで処理が呼ばれる。
  • マイグレーション処理が行われると、DBにmigrationsテーブルが作成され、最後に実行されたマイグレーションの情報(モデル名と日付)が保存され、次回以降はこの日付以前の処理は行われない。


従って、何回も実行確認したいと思ってもファイル名の日付部分を変更するかDBを書き換えるかしないとmigration.upが呼ばれないということになります。


また、最初migrationファイルを1つ作って次のようにDBにフィールドを追加する処理を書いていたところ、この処理がエラーになっていました。

migration.up = function(migrator) {
  migrator.db.execute('ALTER TABLE ' + migrator.table + ' ADD COLUMN age INT;');
};

原因は、この処理を実行する時点で変更しようとしているテーブルが存在していないためでした。
アプリを一旦削除して何にもデータの無い状態で実行すると、モデルのDBテーブルが作成される前にこの処理が走ってしまうため、エラーとなります。

解決策としては、最初に呼ばれるマイグレーションの処理(ファイル名の日付が最も新しいもの)に、テーブルを新規作成する処理を書いて置きます。

migration.up = function(migrator) {
  migrator.createTable({
        "columns":  {
            "name": "TEXT"
        }
    });
};

これで、まっさらな状態からでもDB作成->カラム追加となって問題なくなります。