便利機能を見つけたので紹介します。
次のような処理があったとします。
カラム追加
change_table :users do |t|
t.string :name
end
それを revert ブロックで囲めば逆の処理が走ります。
カラム削除
revert do
change_table :users do |t|
t.string :name
end
end
既存の migtation を丸ごと revert したい場合はそのクラスを指定するだけでよいようです。
既存のmigration定義をrevertする
revert CreateUsers
以下は確認用コードです。
require "active_record"
ActiveRecord::VERSION::STRING # => "5.1.4"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
class A < ActiveRecord::Migration[5.1]
def change
create_table :users do |t|
t.string :name
end
end
run self
end
class B < ActiveRecord::Migration[5.1]
def change
# users を drop
revert A
# 逆の逆の逆の逆なので users を create
revert do
revert do
revert do
revert A
end
end
end
# 再び users を drop
revert A
# users を create
ActiveRecord::Migration.run A # A.migrate(:up) でも実行できる
# 「nameカラム追加」の逆なので「nameカラムを削除」
revert do
change_table :users do |t|
# 本当は string 型だけど嘘を書いてもいい
t.integer :name
end
end
# users を drop
revert do
create_table :users
end
end
run self
end
# >> -- create_table(:users)
# >> -> 0.0018s
# >> -- drop_table(:users)
# >> -> 0.0001s
# >> -- create_table(:users)
# >> -> 0.0003s
# >> -- drop_table(:users)
# >> -> 0.0001s
# >> -- create_table(:users)
# >> -> 0.0002s
# >> -- remove_column(:users, :name, :integer, {})
# >> -> 0.0046s
# >> -- drop_table(:users)
# >> -> 0.0001s
drop や remove 系メソッドに変換しなくてもいいのが楽ですね。