你如何使remove_column可逆?

46 ruby-on-rails rails-migrations

我有一个删除列的迁移:

def change
  remove_column :foos, :bar, :boolean
end
Run Code Online (Sandbox Code Playgroud)

当我尝试rake db:rollback迁移时,我收到以下错误:

remove_column is only reversible if given a type.
Run Code Online (Sandbox Code Playgroud)

ActiveRecord的::迁移文件说,下面是签名remove_column:

remove_column(table_name, column_name, type, options)
Run Code Online (Sandbox Code Playgroud)

所以我在这种情况下的类型应该是:boolean,并且我希望迁移是可逆的.我错过了什么?

我当然可以打破这一点为updown迁移来避免这个问题,但我想明白为什么change语法是不是在这种情况下工作.

pdo*_*obb 77

只需将第三个参数(列的:类型)添加到remove_column方法中,就可以实现迁移的可逆性.所以OP的原始代码确实有效,如:

remove_column :foos, :bar, :boolean
Run Code Online (Sandbox Code Playgroud)

这个答案的其余部分是试图发现为什么这种方法不起作用,但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
Run Code Online (Sandbox Code Playgroud)

我给了这个镜头...在我的Rails 4.1.2应用程序上设置迁移,并且迁移工作方式 - 向上和向下.这是我的迁移:

class TestRemoveColumn < ActiveRecord::Migration
  def change
    remove_column :contacts, :test, :boolean
  end
end
Run Code Online (Sandbox Code Playgroud)

我也尝试了:boolean缺失的参数并得到了与你所说的相同的错误.你确定你在Rails 4.1.2的最终版本 - 不是发布候选版本之一吗?如果你是,我建议binding.pryinvert_remove_column方法的Rails源代码中检查参数列表,看看发生了什么.为此,只需运行bundle open activerecord然后探索:lib/active_record/migration/command_recorder.rb:128.

  • 这确实有效,但这里有一个巨大的警告:如果您要删除包含引用的列(如“user_id”),您可能在该列上有一个索引,Rails 4+ 会在“remove_column”上自动删除该索引. 如果你恢复这个迁移,即使你指定了列类型(比如`:integer`),它也不会在列上重新添加索引,这会给你带来巨大的性能问题。因此,我建议多花一点时间来编写有关迁移的 up 和 down 方法。 (2认同)