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_column
やremove_column
の時は正しくdown
を書く必要があります。
db:migrate:redo
をやってからコミットすれば安心ですね。