[Rails 3] 失敗しないmigrationを書こう

migrationは、いったん他の人と共有してしまったら、容易に変更できず、基本的に追加するのみです。

うっかり環境依存なmigrationを書いてしまっても、自分や既に開発しているメンバーは気づかないことが多いのですが、
新メンバーが参加したり、本番デプロイ環境を整備したときに初めて問題に気づくことがあります。

CI環境で問題の早期発見を目指すのはもちろんですが、事前にやりがちなポイントは気をつけておきましょう。

ライブラリのmigration用メソッドに依存しない

たとえばdeviseの旧バージョンでは、t.confirmableなどのメソッドを使用していましたが、これは最新版ではDEPRECATEDになっています。

また、t.authenticatableを使用した際、バージョンによりpassword_saltが自動生成されるものとされないものがあります。

プロジェクト開始時からライブラリのバージョンを上げた場合、このようなメソッドを使っていると、エラーになったり生成されるカラムが変更されたりするので、データベースに矛盾が生じてしまいます。
特に理由が無ければ、t.string :passwordのように標準機能で記述するのがおすすめです。

モデルクラスを使わない

migration内でデータの検査や変更をする場合など、ActiveRecordのモデルを使いたくなりますが、これは危険です。
migrationは基本的にずっと残るので、仮に将来そのモデルファイルが削除された場合、rake db:migrate:resetが通らなくなってしまいます。
SQLを直接使用するか、以下のように一時的にActiveRecord::Baseを継承したクラスを作るなどの対策が必要です。

Object.const_set "User", Class.new(ActiveRecord::Base)

インデックスの長さに注意する

add_indexでリンクを張る際、長いテーブル名では、気をつけないと64文字を超えてしまうことがあります。
MySQLでは、インデックス名は基本的に64文字以下にする必要がありますが、バージョンによってはそれ以上でも通るので、気づくのが遅れると面倒なことになることがあります。

事前に、長いテーブルやカラム名の場合、インデックスには名前を付けておきましょう。

# 例: MangaRebornでは、投稿されたファンアートや翻訳をすぐに公開するかどうか、選択することができます.
# 仮に複合インデックスを張るとすると、64文字を超えます
add_index, :manga_artists,
           [:allow_publish_fan_art_immediately, 
            :allow_publish_translation_immediately], 
            :name => 'index_manga_artists_1

downをちゃんと書く

当然ですが、downをちゃんと書きましょう。

Rails 3.1以降ではchangeが使えますが、これはcreate/add系で自動処理してくれるだけなので、change_columnremove_columnの時は正しくdownを書く必要があります。

db:migrate:redoをやってからコミットすれば安心ですね。

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

baba

ゆとりプログラマー。 高校時代から趣味でプログラミングを初め、そのままコードを書き続けて現在に至る。慶應義塾大学環境情報学部(SFC)卒業。BPS設立初期に在学中から参加している最古参メンバーの一人。Ruby on Rails、PHP、Androidアプリ、Windows/Macアプリ、超縦書の開発などを気まぐれにやる。軽度の資格マニアで、情報処理技術者試験(16区分17回 + 情報処理安全確保支援士試験)、技術士(情報工学部門)、Ruby Programmer Gold、AWSソリューションアーキテクト(アソシエイト)、日商簿記2級、漢検準1級などを保有。

babaの書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ

BPSアドベントカレンダー