はじめに
Railsのマイグレーションで新しいカラムを追加した直後に、そのカラムを使って既存データを更新したい場面があります。
その際に必要となるのがreset_column_informationです。本記事はその学習記録です。
reset_column_informationとは
reset_column_informationは、マイグレーション中にスキーマ変更を即座にモデルに反映させるためのメソッドです。
内部的にはテーブルのカラム情報キャッシュをクリアし、最新のスキーマを再読み込みして新しいキャッシュを生成します。
使用例
例えば、projectsテーブルにarchivedというフラグを追加し、1年以上前のプロジェクトを自動的にアーカイブしたいとします。
その場合のマイグレーションは以下のようになります。
class AddArchivedToProjects < ActiveRecord::Migration[7.2]
def up
# booleanカラムを追加
add_column :projects, :archived, :boolean, default: false, null: false
# モデルに最新のカラム情報を反映
Project.reset_column_information
# 既存データを一括で更新
Project.where("created_at < ?", 1.year.ago).update_all(archived: true)
end
def down
remove_column :projects, :archived
end
end
この例のポイント
-
add_column直後はDBにはカラムが存在するが、Projectモデルはarchivedカラムをまだ認識していない - そのまま
update_all(archived: true)を実行すると、エラーや不整合が発生する可能性がある -
reset_column_informationを呼ぶことで、モデルに最新のスキーマを再読み込みさせることができる
おわりに
スキーマを変更した直後に、そのカラムを使ってデータを更新する場合にはreset_column_informationが必須です。
一方で、単にカラムを追加するだけでデータ更新を行わない場合には不要です。
あわせて注意したい点は以下の通りです。
- 更新時はシンプルなSQLを使う
-
update_allやexecute "UPDATE ..."のようなメソッドを使う方が安全 -
update!などを使うとバリデーションやコールバックが発生し、コード変更の影響を受けやすい
-
- 大規模データの更新はマイグレーションではなく、Rakeタスクなどで別途実行する