動かざることバグの如し

近づきたいよ 君の理想に

rails db:migrateでALTER TABLEする時は気をつけろという話

結論

    reversible do |direction|
      direction.up { execute "ALTER TABLE battles ADD PRIMARY KEY (id);" }
    end

環境

なぜつけるのか

railsマイグレーションでindexつけたりとか特殊なことをしようとするときはexecute()を使うこともあると思う。

が、db:migrateは成功するものの、

== 20180611044744 CreateBattles: migrating ====================================
-- create_table(:battles, {:id=>false})
   -> 0.1625s
-- execute("ALTER TABLE battles ADD PRIMARY KEY (id);")
   -> 0.2046s
== 20180611044744 CreateBattles: migrated (0.3674s) ===========================

db:rollbackで戻ろうとするとActiveRecord::IrreversibleMigrationでコケる。

== 20180611044744 CreateBattles: reverting ====================================
rails aborted!
StandardError: An error has occurred, all later migrations canceled:



This migration uses execute, 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.


/db/migrate/20180611044744_create_battles.rb:43:in `change'
bin/rails:4:in `<main>'

Caused by:
ActiveRecord::IrreversibleMigration: 

This migration uses execute, 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.


/db/migrate/20180611044744_create_battles.rb:43:in `change'
bin/rails:4:in `<main>'
Tasks: TOP => db:rollback
(See full trace by running task with --trace)

冒頭で書いたように、ちゃんとreversibleブロックの中で実行すると大丈夫 reversibleは可逆の意味

    reversible do |direction|
      direction.up { execute "ALTER TABLE battles ADD PRIMARY KEY (id);" }
    end

詳しくは以下

Active Record マイグレーション | Rails ガイド 3.9 reversibleを使用する

本来はdownも書くんだけど、今回はprymary keyの追加なので割愛