Clojure
ClojureDay 4

マイグレーションを行うmigratusを紹介

はじめに

すいません、完全に言い訳ですが仕事忙しくて....アドベントカレンダー遅れちゃいました・・orz
ほんと、すいません。

DBのマイグレーションを行うmigratus

今回はデータベースのマイグレーションを行うためのClojureのライブラリ、migratusを紹介します。

自分は普段はRailsを使って開発する機会が多く、Railsでのマイグレーションと似たことをClojureでも行えるようにしたいと思って、このライブラリを使っています。

導入

インストール

まずmigratusとleinのmigratusプラグインlein-migratusをproject.cljに記述してインストールします。
ちなみにDBにmysqlを使うため、java.jdbcとmysql-connector-javaも一緒にインストールします。

project.clj
(defproject migratus-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [migratus "0.8.7"]
                [org.clojure/java.jdbc "0.3.7"]
                 [mysql/mysql-connector-java "5.1.36"]]
  :plugins [migratus-lein "0.1.7"])


$ lein deps

接続情報を記述する

DBにマイグレーションをかけるのでもちろん接続情報を伝える必要があります。
接続情報は以下のようにproject.cljの:migratus:ブロックに記述していきます。

project.clj
:migratus {:store :database
            :migration-dir "migrations"
            :db {:classname "com.mysql.jdbc.Driver"
                 :subprotocol "mysql"
                 :subname "//localhost/workspace"
                 :user "admin"
                 :password "hogehoge"}

:migration-dirで上記のように"migrations"と指定すると、マイグレーションファイルがresources/migrations/以下にあると指定している意味になります。

マイグレーションの書き方

migratusで記述するマイグレーションの内容はRailsのようのDSLではなく、純粋なSQLを書きます。マイグレーションを適応するときに、ロールバックするときそれぞれで実行するSQLを記述します。シンプルですね!

マイグレーションファイルを作る

マイグレーションファイルは命名規則に従ったファイル名をつけなければいけないのですが、lein-migratusプラグインを使って作ると勝手に命名規則にあったファイルを作ってくれるのでまずそれを利用してファイルを作ります。

$ lein migratus create users
creating migration files for users
$ ls resources/migrations                                                                                   
20151206003056-users.down.sql 20151206003056-users.up.sql

migrationを書く

上記のようにlein-migratusプラグインでファイルを作成するとファイル名にupがついたファイルとdownがついたファイルがあります。

これはupがマイグレーションをすすめるとき、downが戻るときに実行するSQLを記述します。
以下に適当な例を載せておきます。

20151206003056-users.up.sql
CREATE TABLE IF NOT EXISTS users(
       `id` int(11) NOT NULL AUTO_INCREMENT,
       `account_name` varchar(255) NOT NULL,
       `password` varchar(255) NOT NULL,
       `email` varchar(255) NOT NULL,
       `created_at` datetime NOT NULL,
       `updated_at` datetime NOT NULL,
       PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--;;
ALTER TABLE users ADD INDEX user_email_idx(email);
20151206003056-users.down.sql
ALTER TABLE users DROP INDEX user_email_idx;
--;;
DROP TABLE users;

上記のように一回のマイグレーションで複数のSQLを実行する場合は--;;で区切ると上から順に実行されます。

migrationを実行する

マイグレーションを前に進めるには以下のコマンドを実行します。

$ lein migratus migrate

マイグレーションを元に戻す場合は、以下のコマンドです

$ lein migratus rollback

簡単ですね!!
rubyを使っているときはDSLが定義されたライブラリ使うのが当たり前だったんですが、DBに関わることはSQLを直接書く方がわかりやすいですし覚えることが少ないので、こういうシンプルなツールはいいです^^