你如何使remove_column可逆?

时间:2014-07-01 23:11:18

标签: ruby-on-rails rails-migrations

我有一个删除列的迁移:

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语法不是{\ n}在这种情况下工作。

2 个答案:

答案 0 :(得分:71)

只需将第三个参数(列的类型)添加到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

无论如何,这个文档似乎已经过时了......挖掘the source on 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的最终版本上 - 不是发布候选版本之一吗?如果您是,我建议将binding.pry放入Rails源代码中,以便invert_remove_column方法检查参数列表,看看发生了什么。为此,只需运行bundle open activerecord,然后浏览: lib / active_record / migration / command_recorder.rb:128

答案 1 :(得分:1)

您可以使用changeup方法迁移,而不是使用down

def up
  remove_column :foos, :bar
end

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