web-dev-qa-db-ja.com

remove_columnをリバーシブルにするにはどうすればよいですか?

列を削除する移行があります:

def change
  remove_column :foos, :bar, :boolean
end

rake db:rollbackその移行、次のエラーが表示されます。

remove_column is only reversible if given a type.

ActiveRecord :: Migration ドキュメントには、以下がremove_column

remove_column(table_name, column_name, type, options)

したがって、この場合の私の型は:boolean、そして移行は可逆的であると期待しています。私は何が欠けていますか?

確かにこれをupdownの移行に分けてこの問題を回避できますが、この場合change構文が機能しない理由を理解したいと思います。 。

44
user1454117

3番目の引数(列の:type)をremove_columnメソッドに追加するだけで、その移行を元に戻すことができます。そのため、次のように、OPの元のコードは実際に機能しました。

remove_column :foos, :bar, :boolean

この回答の残りの部分は、この方法が機能しなかった理由を発見する試みでしたが、OPは最終的に機能するようになりました。


ActiveRecord :: Migration :のドキュメントに多少矛盾した情報があります。

remove_columnなどの一部のコマンドは元に戻せません。これらの場合に上下に移動する方法を定義したい場合は、前と同じように上下のメソッドを定義する必要があります。

可逆的なコマンドのリストについては、ActiveRecord :: Migration :: CommandRecorderをご覧ください。

そして、これは ActiveRecord :: Migration :: CommandRecorder

ActiveRecord :: Migration :: CommandRecorderは、移行中に実行されたコマンドを記録し、それらのコマンドを逆にする方法を知っています。 CommandRecorderは、次のコマンドを反転する方法を知っています。

add_column

add_index

add_timestamps

create_table

create_join_table

remove_timestamps

rename_column

rename_index

rename_table

とにかく、このドキュメントは古くなっているようです... githubのソース

あなたに悲しみを与えている方法は次のとおりです。

def invert_remove_column(args)
  raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." if args.size <= 2
  super
end

私はこれを試してみました... Rails 4.1.2アプリで移行をセットアップし、移行は上下に機能しました。ここに私の移行がありました。

class TestRemoveColumn < ActiveRecord::Migration
  def change
    remove_column :contacts, :test, :boolean
  end
end

また、:boolean引数が欠落している状態で試してみましたが、あなたが話しているのと同じエラーが発生しました。 Rails 4.1.2の最終バージョンではありますか?リリース候補の1つではありませんか?ある場合は、binding.pryを置くことをお勧めしますRails invert_remove_columnメソッドのソースを使用して、引数リストを検査し、何が起こっているのかを確認します。これを行うには、bundle open activerecordを実行し、次の場所に移動します:lib/active_record/migration/command_recorder.rb:128

75
pdobb

changeを使用する代わりに、upおよびdownメソッドを使用して移行します。

def up
  remove_column :foos, :bar
end

def down
  add_column :foos, :bar, :boolean
end
2
bratsche