Ruby on Rails : migration 機能でデータベーススキーマを変更する
本日は Ruby on Rails による Web アプリケーション作成の続きです。前回の記事では、Scaffold を使用して記事データ入力の基本的なインターフェースを作成するところまでやりました。generate スクリプトを実行するだけでテーブルのリスト表示・項目作成・編集・削除のすべての操作が実装されるのは驚きでしたね。本日は、前回手動で行ったテーブルの作成作業を Ruby on Rails に任せるための migration と呼ばれる方法をご紹介します。
概要
migration は簡単に言うと Ruby スクリプトによってテーブルの作成やカラム構成の変更を行う機能です。Scaffold 主に導入時のサポートを目的とした機能でしたが、migration はデータベース構成の維持管理を主目的にしています。最大の特徴はテーブル・カラム構成(スキーマと言うんですかね)にリビジョン管理のような概念を導入していることでしょう。migration を使用すると、スキーマを過去のある時点のものに簡単に戻すことができます(テーブル・カラム構成のみで、データが復元されるわけではありません)。これにより、過去のバージョンを動作させるのに必要な構成のデータベースを瞬時に作成することができます。また、実行環境を別のマシンに移すときに、データベースのセットアップを自動化することも可能です。
もうひとつ、スキーマの変更作業をデータベースエンジンに依存しない方法で記述できることも migration の大きな利点です。スキーマの変更をすべて migration で記述することにより、いつでもデータベースエンジンを変更することができるようになります(既存データの移行は別途必要ですが)。
前回は説明を省くために手動でテーブルを作成しましたが、migration の使い方を覚えた後は、最初のテーブルから migration で作成していくのが理想だと思います。
使用方法
それでは、migration を使ったスキーマの変更方法を見ていきましょう。migration 機能を使用するには、少なくともデータベース・ユーザーの作成と設定("config/database.yml" や日本語まわりの設定)が済んでいる必要があります。それらの詳細は前回の記事をご参照ください。
migration の作成
まず最初に、お馴染み generate スクリプトによって新たな migration を作成します。書式は以下のようになります。
ruby script/generate migration <クラス名>
クラス名というのは今回の migration を記述するクラスのクラス名です。1 回の migration ごとに個別の Ruby クラスを作成しますので、ユニークなクラス名を指定してください。 Ruby のクラス名の規則に従い、先頭は大文字のアルファベットでなければなりません。
上記のように generate スクリプトを実行すると、"db/migrate" の中に "<数字3桁>_<クラス名>.rb" というファイル名で Ruby スクリプトが生成されます。先頭の 3 桁の数字はバージョン番号を表しており、migration を作成するごとに 1 ずつ増えていきます。また、クラス名は通例どおり小文字&単語区切り "_" に変更されています。
スキーマ変更の記述
生成されたスクリプトは以下のような内容になっています。
class <クラス名> < ActiveRecord::migration def self.up end def self.down end end
self.up メソッドにはアップグレードの方法、self.down メソッドにはダウングレードの方法を記述します。つまり、self.up でテーブルを作成する処理を記述したら、self.down ではそのテーブルを削除する処理を記述しなければなりません。こうすることで、変更の適用と取り消しが自由に行えるようになります。これがきちんと対称をなしていないとスキーマを巻き戻したときにおかしなことになりますので、注意してください。
それぞれのメソッド内では、テーブル作成・削除やカラム構成変更のためのメソッドが使用できます。それらのメソッドの詳細に関しては次回でご紹介しようと思いますので、今回は割愛します。ご了承ください。m(_ _)m
migration の適用
記述した migration を実際に適用するには、rake というコマンドを使用します。rake は Ruby 版 make とも言うべきビルドスクリプトの実行コマンドで、 Ruby on Rails でも多用されています。migration を適用する場合には rake を以下のように実行します(プロジェクトが "~/blognavi" にあることを前提にしています)。
cd ~/blognavi
rake db:migrate
これを実行すると、"db/migrate" にある migration スクリプトを順番に実行していきます。そしてデータベースに "schema_info" というテーブルを作成し、現在のバージョン番号を記録します。これによって同じスクリプトを重複して適用するのを避けるわけです。次回、また新しく migration を追加して上記のコマンドを実行すると、"schema_info" に記録されているバージョン番号を基点として、それ以降のスクリプトのみを実行するようになっています。
また、以下のようにバージョン番号を指定して実行することもできます。
rake db:migrate VERSION=1
こうすると、スキーマを指定したバージョンの状態に戻すことができます。これは便利ですね(^^)
実例
それでは、実例としてテーブルを作成する migration を追加してみましょう。前回は記事データを格納するテーブルを作成しましたので、今回はカテゴリーを格納するテーブルを作成しようと思います。テーブル名は "categories" で、カラム構成はとりあえず以下のようにしましょうか。
カラム名 | データ型 | 内容 |
---|---|---|
id | INT | 固有 ID |
name | VARCHAR(200) | カテゴリー名 |
まずは migration を作成します。
cd ~/blognavi
ruby script/generate migration AddCategoryTable
次に、"db/migrate/001_add_category_table.rb" を以下のように変更します。念のため :options でテーブルの形式と文字コードも設定しておきます。
class AddCategoryTable < ActiveRecord::migration def self.up create_table(:categories, :options => "ENGINE=MyISAM DEFAULT CHARACTER SET=UTF8") do |t| t.column(:name, :string, :limit => 200, :null => false) end end def self.down drop_table(:categories) end end
そして、migration を実行します。
cd ~/blognavi
rake db:migrate
これで "blognavi" データベースに上記の "categories" テーブルが追加されているはずです。 mysql コマンドで確認すると、以下のようにテーブルが作成されているはずです。
mysql> describe blognavi.categories; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | id | int(11) | | PRI | NULL | auto_increment | | name | varchar(200) | | | | | +-------+--------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)
以上、 Ruby on Rails の migration 機能の使い方をご紹介しました。この機能は VALUE DOMAIN のサーバーに実行環境を移す際にも再度活躍してもらう予定です。複数の migration をまとめてひとつの操作としてエクスポートできるので、サーバー移行時のスキーマ設定が自動化が可能です。その方法はまたそのときにご紹介しますので、お楽しみに(^^)。次回はまとめ編として、今回割愛してしまった migration スクリプト内で使用できるメソッドの詳細などをご紹介する予定です。シンプルながら必要な機能はほとんど網羅されていて、なかなかのものです。それでは、本日はこのへんで。
詳しくはこちらの記事をどうぞ!
この記事にコメントする