Edited at

migration 時にデータを操作するのは悪手か?

※ 2019/4/25 追記:別途 rake task を用意する派だったが、管理する環境が増えてスクリプトの実行漏れが発生するので この記事で紹介されている migration_data という Gem が良さそうなので試してみたい。


とりあえずの結論


  • migration スクリプト内ではモデル独自のメソッド、アトリビュート等に依存した処理は書くべきでは無い


    • それらのメソッド、アトリビュートはDBの物理的な構造に関係無く変更されるもの

    • 将来それらを削除したり変更した際にmigrationが動かなくなる可能性がある



  • どのメソッドが良くてどれがダメか判断が難しい場合、SQLを直に書くのもアリ




発端

マイグレーションにより新しいカラムを追加するけど、その値をマイグレーションで入れるべきかについてプロジェクトで話が出たので、過去に見つけた以下のブログを読んで理解した内容をまとめてみる。

Data Migrations in Rails


migration でデータを操作するのがダメな理由



  • db/migrate にずっと残り続ける、将来性に乏しい



    • 将来、クラスが変更になった際にマイグレーションが動かなくなる


      RailsでDBのデータ変更はどこに書く? - komagataのブログ

      「ふつうこうだよ」という話ではないのですが、migraitonの中でARのオブジェクトを使いすぎると困ることがあるのであまり使わないようにはしています。

      たとえば1年後に、その属性やメソッドの無くなったとすると、そのタイミングで一からマイグレーションすると死亡する。という感じです。




    • ビジネスロジックと無関係なものがコードに残り続ける


    • ローカルの開発環境だと頻繁にDB作り直しするケースが多いがその場合にも同じ処理がなんども流れてムダ?





  • db:migrate ではなく db:schema:load, db:reset の場合は実行されない


    • 後者は schema.rb (schema.sql) を単に実行しているから

    • そのような場合に期待した結果とならない場合もある




  • デプロイとデータ更新が密接に結びつく


    • 大量のデータを更新しなければならないとしたらマイグレーションの実行に多くの時間がかかる

    • その間、アプリケーションが実行できずサービス停止する必要がある




代替案(migrationに書かない場合)


  • テンポラリのrakeタスクを用意する

  • seed.rb に書く

かな?


関連リンク


ToDo


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

migrationファイル内では、モデルクラスを使わないのが安全です。

これは、将来的に仕様変更やリファクタでそのモデルがなくなったりリネームされた際、rake db:migrate:resetが通らなくなるからです。


上記のケースについて現在のRailsでの挙動を確認する