🖥

#Rails + MySQL で timestamps のマイグレーションを忘れていたので後から created_at / updated_

2019/12/29に公開

points

  • null を許可してカラムを追加する。
  • 全てのレコードに値を入れる。
  • null を不許可に変える。

warning

カラム1個を追加する場合は timestams でもなく timestamp でもなくて datetime を指定することに注意。

( あなたの Rails の t.timestamps は datetime 型のカラムを MySQL に追加しているか? 環境によるかもしれない。確認してほしい )

migration

class AddCreatedAtToUser < ActiveRecord::Migration[5.2]
  def up
    add_column :users, :created_at, :datetime, null: true

    User.update_all(created_at: Time.current)

    change_column :users, :created_at, :datetime, null: false
  end

  def down
    remove_column :users, :created_at
  end
end

既存レコードを作った上で

bundle exec rails db:migrate
bundle exec rails db:rollback

などを実行して試してみよう。

null を許可せずにカラム追加した場合

null を許可しない場合、既存レコードがあるとエラーでmigrationがキャンセルされてしまう。

class AddCreatedAtToUser < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :created_at, :datetime, null: false
  end
end
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Incorrect datetime value: '0000-00-00 00:00:00' for column 'created_at' at row 1: ALTER TABLE `users` ADD `created_at` datetime NOT NULL

...

Caused by:
ActiveRecord::StatementInvalid: Mysql2::Error: Incorrect datetime value: '0000-00-00 00:00:00' for column 'created_at' at row 1: ALTER TABLE `users` ADD `created_at` datetime NOT NULL

デフォルトを指定した場合

class AddCreatedAtToUser < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :created_at, :datetime, null: false, default: -> { 'NOW()' }
  end
end

migrationは出来るがカラムに default値が設定されてしまい、 テーブル作成時に t.timestamps を指定した状態とは違ってしまう。

  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,

デフォルト値を指定し、後から削除しようとした場合

サーバー設定のせいかうまく行かなかった。

class AddCreatedAtToUser < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :created_at, :datetime, null: false, default: -> { 'NOW()' }
    change_column :users, :created_at, :datetime, null: false, default: ''
  end
end
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Invalid default value for 'created_at': ALTER TABLE `users` CHANGE `created_at` `created_at` datetime DEFAULT NULL NOT NULL
...

Caused by:
ActiveRecord::StatementInvalid: Mysql2::Error: Invalid default value for 'created_at': ALTER TABLE `users` CHANGE `created_at` `created_at` datetime DEFAULT NULL NOT NULL

Ref

mysqlにカラムを追加しようとしたらInvalid default value for エラー - Qiita
https://qiita.com/rh_/items/be798e69a8f9000c56b1

Setting MySQL DATETIME column defaults in Rails
https://www.mikeperham.com/2014/05/17/setting-mysql-datetime-column-defaults-in-rails/

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2883

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ

Twitter

https://twitter.com/YumaInaura

公開日時

2019-12-29

Discussion