環境
- Rails 5.2.2
想定されるシチュエーション
- migrationの中でカラムを追加した後に、併せてデータを追加したい。
-
reset_column_informationを使って、modelが確実に新しいカラムを持っているようにする。 - 参考
-
- migrationを書いた後になってから、クラス名が変わる場合がある。
- クラスとテーブルがmigrationファイルの中で整合性が取れるように、クラス定義をする。
参考
例1
class AddStatusToStripePayments < ActiveRecord::Migration[5.2]
class StripePayment < ApplicationRecord
self.table_name = :stripe_payments
end
def change
add_column :stripe_payments, :object, :string
add_column :stripe_payments, :status, :string
StripePayment.reset_column_information
reversible do |dir|
dir.up do
StripePayment.find_each do |payment|
resp = payment.response
payment.update!(object: resp['object'], status: resp['status'])
end
change_column :stripe_payments, :object, :string, null: false
change_column :stripe_payments, :status, :string, null: false
end
end
reversible do |dir|
dir.up do
StripePayment.find_each do |payment|
unless payment.object.present? && payment.status.present?
fail "object and/or status of the payment (id: #{payment.id}) is empty"
end
end
end
end
end
end
例2
class AddFormatToWorks < ActiveRecord::Migration[5.2]
def change
add_column :works, :format, :integer, after: :title
reversible do |dir|
dir.up do
execute("UPDATE works SET format = 0")
change_column :works, :format, :integer, null: false
end
end
end
end
備考
上記では、Railsのソースコード内のコメントに倣って、add_columnした後にreset_column_informationしていますが、ここでは「modelを触ったので後始末としてリセットする」と書かれています。
どっちが正しいんでしょ?(時間がある時に検証します)
追記
- migration_data という gem を使えば、前述のことを考えなくて済むかもしれない。