[Rails] migration スクリプトから model を参照する

migration スクリプトから model を参照したくなる時があります。例えば、あるテーブルに1つのカラムを追加し、他のカラムの値から追加したカラムの値を計算して保存したい場合とか。

でも、考えなしに参照してしまうと、後々 rake db:migrate:resetコマンドを実行した時にエラーが発生する原因になってしまいます。具体的なコードを見てみましょう。

ダメな例

以下はダメなコードの例。users テーブルにカラム c を追加し、その後既存の全レコードに対して、カラム a とカラム b から求めた値をカラム c に保存しています。

すべてのレコードを走査・更新するときに User モデルを参照・利用していますね。

では、このコードは何がダメなんでしょうか。実は、将来的に何らかの理由で User モデルが削除されてしまった場合、この migration スクリプトが実行されると、以下の様なエラーが発生してしまいます。

「User モデルなんて定義されてないよ」と怒られてしまうわけです。

エラーが発生しない例

とりあえず、上記の migration スクリプトをエラー無しで実行できるようにするにはどうすればいいでしょうか。実は、migration スクリプトの中で User モデルを定義することで、エラーを回避できるようになります。

定義がたった一行の中身が何もないモデルですが、テーブルからのデータ取得や更新といった基本的なことはこのモデルから行えます。

もちろん、削除する前のモデルに定義されていたメソッド等は呼び出せないので、注意が必要です。そういう場合は、migration スクリプト内のモデルにも同様のメソッドを実装するか、メソッド呼び出しを伴わない形で migration スクリプトを実装する必要があります。

そもそも model を参照せずに、「SQL文を直接記述する」という方法もありますが、楽できるところは楽したいところ。SQL文を記述する方法については以下の記事を参考にしてください。

それでは!

参考URL

Railsのmigrationで生SQLを使う+パラメータを使う | TechRacho