経緯
初任教育研修で、既存のタスク管理アプリに機能を追加する際に苦戦したときのメモです。
タスク管理アプリに、タスクの期限機能を追加開発する際に、既存のtasksテーブルにduedateカラムを追加しようとしていました。
db:migrateコマンドの実行
まずはTasksテーブルにduedateカラムを追加するためのマイグレーションファイルを作成するためにgenarateコマンドを実行します。
rails g migration AddDueDateToTasks duedate:datetime
これで自動的に以下のようなマイグレーションファイルができました
class AddDueDateToTasks < ActiveRecord::Migration[7.1]
def change
add_column :tasks, :duedate, :datetime
end
end
マイグレーションファイルの編集の際に陥った勘違い
まず、自分が勘違いして書いた間違ったコードがこちら
class AddDueDateToTasks < ActiveRecord::Migration[7.1]
def change
add_column :tasks, :duedate, :datetime, null: false
end
end
duedateのnull falseにしたいから、テーブル生成のときと同じ感覚でここに追記してそのままrails db:migrateを実行してエラーを連発していました。
私と同じ勘違いをしている方のために説明すると、このコマンドでは既存のデータにduedateカラムが追加された際に、それが空になってしまうので矛盾が生じていたというものでした。
そしてその理由がわからないままdb:rollbackとdb:migrateを繰り返して、DBをぐちゃぐちゃにして時間を溶かしていきました。。。。
もし同じように苦しんでいる方がいましたら(本番環境でなかったら)以下のコマンドを実行して次をお読みください。既存のデータが全部なくなるので注意。
rails db:reset
マイグレーションファイルの編集(正解)
私の場合の正解はこんな感じでした。
class AddDueDateToTasks < ActiveRecord::Migration[7.1]
def up
# 最初にduedateカラムをnull許容で追加する
add_column :tasks, :duedate, :datetime, null: true
# 既存のレコードに現在の時間を設定する
execute "UPDATE tasks SET duedate = NOW()"
# null: false制約を適用する
change_column :tasks, :duedate, :datetime, null: false
end
def down
remove_column :tasks, :duedate
end
end
基本的に継続開発を考えた際にはupとdownで記載するべきと知りました。
参考にした記事
【Ruby on Rails】changeとup・downの使い分けについて
また、先ほどの勘違いから流れを修正しました。
- まずはnullを許容して新しくduedateというカラムを作成
- 既存のレコードに対してduedateを記載
- null falseを適用する
このように修正することで無事に
rails db:migrate
が実行できて既存のtasksテーブルにduedateカラムを追加することができました。
up.downで記載したからレビューを受けた後に楽に修正できた
追加機能を実装してレビューを受けたら
『カラム名をduedateからdue_dateに変更してください』
というレビューを受けました。
カラム名を変更するためにまた、マイグレーションファイルを作成するのかと思いましたが、downによりロールバック時の挙動を定めていたので、
rails db:rollback
としてから、
マイグレーションファイルをdue_dateに修正して、
class AddDueDateToTasks < ActiveRecord::Migration[7.1]
def up
add_column :tasks, :due_date, :datetime, null: true
execute "UPDATE tasks SET due_date = NOW()"
change_column :tasks, :due_date, :datetime, null: false
end
def down
remove_column :tasks, :due_date
end
end
もう一回rails db:migrateを実行するだけでテーブルの修正は完了できました。よかった。
まとめ
ということで機能追加のためにテーブルにカラムを追加することができました。誤っている部分がありましたらご指摘していただけると大変助かります。