Seiichi Yonezawa — How creativity is helped by failure

開発日記 #65

今日覚えた(Today I Learned)の簡易版をいつか作って、まとめて検索・閲覧できるようにしようと考えていましたが、わざわざブログに残さなくてもリンクを張ればいいかと思っていました。今週はブログの更新が滞っていたのであえて残してみます。ちなみに内容はマイグレーションですが、ガイドにある内容とあまり変わりません。

If you have to use models in migrations, make sure you define them so that you don't end up with broken migrations in the future

Rails Style Guideより、モデルを用いなければならないときは、あらかじめそのモデルを定義し、将来マイグレーションを壊さないようにしましょう。という但し書きがありました。

これは現在保守をしている古いサイトでも発生していたのですが、何年とmigrationを実行していると現在使用しているモデルが実は存在しないということが起こりえます。テーブルが消えている、あるいはProductがPreparationに変更されていたりなどです。そして、モデルが存在しない結果、過去に実行できていたマイグレーションでNameErrorが発生します。

なので、使い捨て用のモデルを定義することで、SQLを書く必要もなくActiveRecordのメソッドが使用できるというわけ。

class MigrationProduct < ActiveRecord::Base
  self.table_name = 'products'
end

class ExampleMigration < ActiveRecord::Migration[5.0]
  def change
    rename_table :preparetions, :products

    old = 'approved'
    new = 'approval'

    reversible do |dir|
      dir.up do
        Product.where(status: old).update_all(status: new)
      end
      dir.down do
        Product.where(status: new).update_all(status: old)
      end
    end
  end
end

そしてここで登場したreversiblerake db:migrateproductsテーブルにリネームしたあとに、ステータスの名称を変更するという流れをrake db:rollbackしたときにステータスを元に戻した後にpreparationsへ元に戻すというなかなか高度な処理を行ってくれるようです(実際にこの例では試していませんが)。

ちょくちょくRails Style Guideも更新されるようなので、参考になりますね。