こんにちは!
4月に入社した新人エンジニアのodaです。
Ruby on Railsを使ってアプリケーション開発をされている方は、マイグレーション機能を使ってテーブル定義に変更を加えているかと思います。
私自身、個人でRailsアプリを作成しているときは、もちろん、マイグレーション機能を使っていたのですが、ロールバックを意識することがなく、マイグレーションファイルの「change」と「up・down」の違いがわかっていませんでした。
今回は、この点について、掘り下げてみたいと思います。
(以下、Rails 7.0.2.3を使用しています。)
まずは、次のコマンドにより、Usersテーブルを作成します。
bin/rails g model Users name:string age:integer note:string
すると、次のようなマイグレーションファイルが作成されます。
class CreateUsers < ActiveRecord::Migration[7.0] def change create_table :users do |t| t.string :name t.integer :age t.string :note t.timestamps end end end
このマイグレーションファイルを次のコマンドにより実行するとname、age、noteのカラムを持ったUsersテーブルが作成されます。
bin/rails db:migrate
さて、次のコマンドを実行するとどうなるでしょうか?
bin/rails db:rollback
直前に行ったマイグレーションがロールバックされ、Usersテーブルが削除されます。
このとき、Railsは、changeメソッドを逆転実行するとどうなるかを自動的に判断してくれています。(「テーブルの追加」の逆は「テーブルの削除」)
次にnoteのデータ型をstringからtextに変更するために、以下のマイグレーションファイルを作成、実行します。
class ChangeDatatypeNoteOfUsers < ActiveRecord::Migration[7.0] def change change_column :users, :note, :text end end
すると、noteのデータ型はstringからtextへ変更されます。
この時、先ほどのrollbackコマンドを実行するとどうなるでしょうか?
次のようなエラーメッセージが出るかと思います。
rails aborted! StandardError: An error has occurred, this and all later migrations canceled: This migration uses change_column, which is not automatically reversible. To make the migration reversible you can either: 1. Define #up and #down methods in place of the #change method. 2. Use the #reversible method to define reversible behavior.
要約すると、change_column
を使用したマイグレーションは自動的には元に戻せないため、1もしくは2の方法をとってくださいと書かれています。
それでは、方法1を使って、先ほどのマイグレーションファイルを次のように書き換えてみます。upメソッドにはマイグレーション時の処理を、downメソッドにはロールバック時の処理を書きます。
class ChangeDatatypeNoteOfUsers < ActiveRecord::Migration[7.0] def up change_column :users, :note, :text end def down change_column :users, :note, :string end end
すると、無事、ロールバックをすることができるようになります。
また、方法2を使うと、次のようにマイグレーションファイルを書き換えることもできます。
class ChangeDatatypeNoteOfUsers < ActiveRecord::Migration[7.0] def change reversible do |dir| change_table :users do |t| dir.up { t.change :note, :text } dir.down { t.change :note, :string } end end end end
マイグレーションファイルを使うときは、上記を意識することで、スムーズに開発を進めていきたいと思います。
ちなみに、changeメソッドが逆転実行できるのは、add_column
、 change_column_null
、create_table
、rename_column
など、あらかじめ決められたメソッドに限られています。
みなさんも、マイグレーション機能により、テーブル定義に変更を加えるときは、ぜひ、意識してみてください!