TL;DR
migrate後のmigrationファイルを書き換えると、データの値が荒れがち。
rubocopに「直したほうが良い」と言われようとも、migrationファイルは書き換えないのが基本。
(自戒の念を込めて記事化)
状況
rubocopで静的解析をかけた時のお話。
こんな表示が出ました。
db/migrate/20210827131348_add_activations_to_users.rb:9:5:
C: Rails/BulkChangeTable:
You can use change_table :relationships, bulk: true to combine alter queries.
「add_columnを何度も重ねずに、add_tableで一括変更してくれ」とのことなので、
そのように変更。
やったこと
"rails db:migrate:status" => ID確認。
"rails db:migrate:down VERSION=xxxxxxx" => downに
その後、migrationファイルを変更してmigrate実行
class AddActivationToUsers < ActiveRecord::Migration[6.1]
def change
add_column :users, :activation_digest, :string
add_column :users, :activated, :boolean, default: false
add_column :users, :activated_at, :datetime
end
end
↓
class AddActivationToUsers < ActiveRecord::Migration[6.1]
def change
change_table :users, bulk: true do |t|
t.string :activation_digest
t.boolean :activated, default: false
t.datetime :activated_at
end
end
end
結果
既に開発環境で存在しているuserのdefault値が変化。
default値は新規作成の時だけ効果発揮するのだと思ってたけど、違うのね…。
[1] pry(main)> User.find(1)
User Load (0.9ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User:0x000055d27e9d5548
id: 1,
name: "正太郎",
…
activated: false, # migration前はactivated: trueだった
このままデプロイすると、本番環境のデータベースに格納されている値も変化してしまって、非常によろしくない。。
改善
-
migrationによってでデータベースに格納されている値を変えてしまうのはよろしくない。
基本的にはmigrationファイルの書き換えはしない。
DBの変更するときはremove_columnとか、change_defaultとか、変更履歴がわかるものにとどめるのが無難だと推察される。 -
rubocop.ymlは以下の通りに変更
Exclude:
- 'db/**/*'
- そもそも、本番環境に関しては定期的にバックアップをとりましょう。