WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

Ruby on Rails : migration 機能リファレンス

本日は Ruby on Rails の migration 機能の続きです。前回の記事では migration 機能の基本的な使用方法をご紹介しました。本日はリファレンス編ということで、migration で使用されるメソッドをご紹介しようと思います。合わせて、migration を記述する上で知っていると便利な Tips もいくつか記載しましたので、ぜひ参考にしてくださいね(^^)

スキーマ変更を行うメソッド

まずはスキーマを変更するためのデータベース操作をラップしたメソッドをご紹介します。前回の記事で使用した create_table 以外にもたくさんのメソッドが用意されています。これだけあれば、ほとんどの操作は SQL を書かずに実現できることでしょう。

なお、これらのメソッドではテーブル名やカラム名を引数として指定するようになっていますが、それらはシンボルで指定してください。具体的には、以下のように名前の前に ":"(コロン )を付けます。

add_column(:table_name, :column_name, ...)

おそらく高速化のためにシンボルを使用しているものと思います。処理内容にもよりますが、Ruby では文字列よりもシンボルのほうが効率よく処理が行えるようです。 Ruby on Rails では随所でシンボルが活用されていますので、早めに慣れてしまいましょう。

では、それぞれのメソッドをご紹介します。

create_table(name, option)

テーブルを作成します。引数の意味は次のとおりです。

name
作成するテーブルの名前。
option
以下の任意の要素を含むハッシュ。
キー
:id false なら id カラムを自動作成しない
:primary_key 主キーのカラム名
:options SQL の最後に付加する文字列
:temporary 一時的なテーブルを作成
:force true なら古いテーブルを削除するしてから作成

また、ブロックを指定することでテーブルに含むカラムを指定することができます。ブロック引数には TableDefinition クラスのインスタンスが渡され、主にその column メソッドでカラムを定義します。column メソッドの引数は後述の add_column メソッドから第 1 引数(テーブル名)を抜いたものです。具体的な使用例は前回の記事をご参照ください。

なお、バックエンドデータベースとして MySQL を使用している場合、:options を指定しないと "ENGINE=InnoDB" がデフォルトで指定されます。

drop_table(name)

指定されたテーブルを削除します。引数の意味は以下のとおりです。

name
削除するテーブルの名前。

rename_table(old_name, new_name)

指定されたテーブルの名前を変更します。引数の意味は以下のとおりです。

old_name
変更前のテーブルの名前。
new_name
変更後のテーブルの名前。

add_column(table_name, column_name, type, options)

カラムを追加します。引数の意味は以下のとおりです。

table_name
カラムを追加するテーブルの名前。
column_name
追加するカラムの名前。
type
データ型の指定。":primary_key", ":string", ":text", ":integer", ":float", ":decimal", ":datetime", ":timestamp", ":time", ":date", ":binary", ":boolean" のうちのいずれか。
options
以下の任意の要素を含むハッシュ。
キー
:limit 文字列などのデータ長
:default カラムのデフォルト値。省略すると NULL になる
:null false なら NULL を禁止する
:precision :decimal 型の精度を指定する
:scale :decimal 型の小数点以下の桁数

rename_column(table_name, column_name, new_column_name)

指定されたカラムの名前を変更します。引数の意味は以下のとおりです。

table_name
名前変更するカラムが存在するテーブルの名前。
column_name
変更前のカラムの名前。
new_column_name
変更後のカラムの名前。

change_column(table_name, column_name, type, options)

指定されたカラムの属性を変更します。引数の意味は以下のとおりです。

table_name
属性を変更するカラムが存在するテーブルの名前。
column_name
属性を変更するカラムの名前。
type
新しいデータ型。指定できる値は add_column と同じ。
options
新しいオプション。指定できる値は add_column と同じ。

change_column_default(table_name, column_name, default)

指定されたカラムのデフォルト値を変更します。このメソッドではデフォルト値を NULL に変更することはできないようです。引数の意味は以下のとおりです。

table_name
デフォルト値を変更するカラムが存在するテーブルの名前。
column_name
デフォルト値を変更するカラムの名前。
default
新しいデフォルト値。

remove_column(table_name, column_name)

指定されたカラムを削除します。引数の意味は以下のとおりです。

table_name
削除するカラムが存在するテーブルの名前。
column_name
削除するカラムの名前。

add_index(table_name, column_name, options)

検索用のインデックスを追加します。インデックスの名前はデフォルトで "<テーブル名>_<最初のカラム名>_index" になりますが、options に :name を指定することで任意の名前を指定できます。引数の意味は以下のとおりです。

table_name
インデックスを作成するテーブルの名前。
column_name
対象カラムの名前。複数のカラムを対称にする場合はシンボル配列で指定する。
options
以下の任意の要素を含むハッシュ。
キー
:name インデックスの名前。
:unique true を指定すると UNIQUE なインデックスになる。

remove_index(table_name, options)

検索用のインデックスを削除します。このメソッドには主に 2 つの呼び出し方があります。最初は削除するインデックスをカラム名で指定する形式で、以下の書式になります。

remove_index(<テーブル名>, :column => <カラム名>)

この形式では、add_index メソッドと同じ方法でインデックス名を作成し、そのインデックスを削除します。複数カラムを対象としたインデックスでも、最初のカラムを指定するだけで削除できることに注意してください。第 2 の形式はインデックス名を直接指定する方法です。

remove_index(<テーブル名>, :name => <インデックス名>)

この形式なら任意の名前のインデックスを削除できます。add_index で名前を指定してインデックスを作成した場合に使用します。

execute(sql)

指定された SQL 文を実行します。このメソッドを使えば SQL で記述可能なすべての処理が行えます。ただし、データベースエンジンに依存してしまう可能性が高いので、特定の環境への依存を避けたい場合は使わないほうが無難かもしれません。引数の意味は以下のとおりです。

sql
実行する SQL 文。

以上、これだけ知っていればほぼ自在に migration が記述できると思います。 SQL は必要以上に複雑な面があるので、それを使わなくていいというのは助かりますね(^^;

Tips

おまけとして、migration を記述する際に知っておくと便利な Tips をご紹介します。無用なトラブルを避けるためにも、目を通していただけるとよいと思いますよ。

ロールバック不可能な変更を行う場合

migration の up メソッドで完全なロールバックが不可能な変更を行う場合(テーブルの削除など?)、down メソッドでは IrreversibleMigration 例外を投げることが推奨されています。以下のような感じでしょうか。

class RemoveFoo < ActiveRecord::Migration
  def self.up
    drop_table(:foo)
  end
 
  def self.down
    raise IrreversibleMigration
  end
end

ただし強制ではないので、重要性が低いと判断すれば例外を投げなくてもよいと思います。

Migration 中のデータ操作

migration の up, down のメソッド中では前述のスキーマ変更メソッドだけではなく、モデルクラスを使用したデータ操作も可能です。以下の例では、前回の記事で作成したカテゴリーテーブルから名前が空文字列になっているカテゴリーを削除しています。

class RemoveEmptyCategories < ActiveRecord::Migration
  def self.up
    Category.find(:all).each do |category|
      category.destroy if category.name.empty?
    end
  end
end

スキーマ変更後のデータ操作

前述のスキーマ変更メソッドでデータベースのスキーマを変更した後にモデルクラスによるデータ操作を行う場合は、モデルクラスの reset_column_information メソッドを呼んでカラムの情報をリセットする必要があります。

class AddUniqueNumber < ActiveRecord::Migration
  def self.up
    add_column(:categories, :number, :integer)
    Category.reset_column_information
    num = 0
    Category.find(:all).each do |category|
      category.number = num
      num += 1
    end
  end
 
  def self.down
    remove_column(:categories, :number)
  end
end

テーブルを UTF-8 対応にする

日本語を扱う場合、テーブルの文字コードを UTF-8 にしておかないと文字化けしてしまう可能性があります。データベース作成時にデフォルトとして UTF-8 を指定しておくのが理想ですが、場合によってはそれが不可能なこともあるでしょう。そういう場合は、create_table メソッドの :options を利用します。前回の記事 と同じ例ですが、以下のような感じです。

class AddCategoryTable < ActiveRecord::migration
  def self.up
    create_table(:categories, :options => "ENGINE=InnoDB DEFAULT CHARACTER SET=UTF8") do |t|
      t.column(:name, :string, :limit => 200, :null => false)
    end
  end
 
  def self.down
    drop_table(:categories)
  end
end

:options を明示的に指定するとデフォルトの "ENGINE=InnoDB" の指定が無効になるので、それも含めてやる必要があります。けっこう忘れがちなので注意してください。

本日は、migration で使用するメソッドをご紹介しました。migration は SQL よりも記述が簡単で、しかもバージョン管理も可能という優れものですから、利用しない手はありません。 Ruby on Rails を使う主なメリットのひとつに数えてしまっても遜色ないと思います。 Ruby on Rails を利用する際は、ぜひ活用してください!(^^)

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles