ruby-on-rails 如何使remove_column可逆?

hjzp0vay  于 2023-01-10  发布在  Ruby
关注(0)|答案(3)|浏览(151)

我有一个删除列的迁移:

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语法在这种情况下不起作用。

jw5wzhpr

jw5wzhpr1#

只需在remove_column方法中添加第三个参数(列的:type),就可以使迁移可逆,因此OP的原始代码实际上是有效的,如下所示:

remove_column :foos, :bar, :boolean

这个答案的其余部分是试图发现为什么这个方法不起作用,但OP最终使它起作用。
我在ActiveRecord::Migration的文档中看到了一些相反的信息:
有些命令如remove_column是不能反转的,如果你想定义在这些情况下如何上下移动,你应该像以前一样定义up和down方法。
有关可逆命令的列表,请参阅ActiveRecord::Migration::CommandRecorder。
下面是ActiveRecord::Migration::CommandRecorder的例子:
ActiveRecord::Migration::CommandRecorder记录迁移期间执行的命令,并知道如何反转这些命令。CommandRecorder知道如何反转以下命令:
添加列
添加索引
添加时间戳
创建表格
创建连接表
删除时间戳
重命名列
重命名索引
重命名_表
无论如何,看起来这个文档已经过时了...在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参数缺失的情况,得到了与您所讨论的相同的错误。您确定您使用的是Rails4.1.2的最终版本--而不是候选发行版之一吗?如果您是,我建议将binding.pry放入Rails源代码中,以便invert_remove_column方法检查参数列表并查看发生了什么。为此,只需运行bundle open activerecord,然后浏览:* 库/活动记录/迁移/命令记录器. rb:128 *。

eyh26e7m

eyh26e7m2#

不使用change,而是使用updown方法进行迁移:

def up
  remove_column :foos, :bar
end

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

yxyvkwin3#

如果您正在批量删除列,您可以使迁移可逆,如下所示(自rails 6. 1起)

def change
    change_table :foobar, bulk: true do |t|
      t.remove :foo, type: :float
      t.remove :bar, type: :int
    end
  end

相关问题