你如何使 remove_column 可逆? [英] How do you make remove_column reversible?
问题描述
我有一个删除列的迁移:
I have a migration that removes a column:
def change
remove_column :foos, :bar, :boolean
end
当我尝试 rake db:rollback
那个迁移时,我收到以下错误:
When I try to rake db:rollback
that migration, I get the following error:
remove_column is only reversible if given a type.
ActiveRecord::Migration 文档说以下是 remove_column<的签名/代码>:
The ActiveRecord::Migration documentation says that the following is the signature for remove_column
:
remove_column(table_name, column_name, type, options)
所以在这种情况下我的类型应该是 :boolean
,并且我希望迁移是可逆的.我错过了什么?
So my type in this case should be :boolean
, and I expect that migration to be reversible. What am I missing?
我当然可以将其分解为 up
和 down
迁移以避免此问题,但我想了解为什么 change
语法在这种情况下不起作用.
I can certainly break this out into an up
and down
migration to avoid this problem, but I'd like to understand why the change
syntax isn't working in this case.
推荐答案
只需将第 3 个参数(列的 :type)添加到 remove_column
方法即可使迁移可逆.所以 OP 的原始代码确实有效,如:
Simply adding the 3rd argument (the column's :type) to the remove_column
method makes that migration reversible. So the OP's original code actually did work, as in:
remove_column :foos, :bar, :boolean
这个答案的其余部分是试图发现为什么这种方法不起作用,但 OP 最终让它起作用.
The rest of this answer was an attempt to discover why this method would not have been working, but the OP ended up getting it to work.
我在 ActiveRecord::Migration 的文档中看到了一些相反的信息:
I see somewhat contrary info in the documentation for ActiveRecord::Migration:
某些命令(例如 remove_column)无法撤消.如果你想定义在这些情况下如何上下移动,你应该像以前一样定义 up 和 down 方法.
Some commands like remove_column cannot be reversed. If you care to define how to move up and down in these cases, you should define the up and down methods as before.
有关可逆命令的列表,请参阅 ActiveRecord::Migration::CommandRecorder.
For a list of commands that are reversible, please see ActiveRecord::Migration::CommandRecorder.
这来自 ActiveRecord::Migration::CommandRecorder:
ActiveRecord::Migration::CommandRecorder 记录迁移期间执行的命令,并知道如何反转这些命令.CommandRecorder 知道如何反转以下命令:
ActiveRecord::Migration::CommandRecorder records commands done during a migration and knows how to reverse those commands. The CommandRecorder knows how to invert the following commands:
add_column
add_index
add_timestamps
add_timestamps
创建表
create_join_table
create_join_table
remove_timestamps
remove_timestamps
rename_column
rename_column
rename_index
rename_index
rename_table
rename_table
无论如何,这个文档似乎已经过时了......深入研究 github 上的源码:
Anyway, it appears that this documentation is out of date... Digging into 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 应用程序上设置了一个迁移,迁移是双向的——向上和向下.这是我的迁移:
I gave this a shot... setup a migration on my Rails 4.1.2 app and the migration worked both ways -- up and down. Here was my migration:
class TestRemoveColumn < ActiveRecord::Migration
def change
remove_column :contacts, :test, :boolean
end
end
我也尝试过使用 :boolean
参数丢失并得到与您所说的相同的错误.您确定您使用的是 Rails 4.1.2 的最终版本——不是候选版本之一吗?如果您是,我建议将 binding.pry
放入 invert_remove_column
方法的 Rails 源代码中,以检查参数列表并查看发生了什么.为此,只需运行 bundle open activerecord
,然后浏览到:lib/active_record/migration/command_recorder.rb:128.
I also tried with the :boolean
argument missing and got the same error as you're talking about. Are you sure you're on the final version of Rails 4.1.2 -- not one of the release candidates? If you are, I'd suggest putting a binding.pry
into the Rails source for the invert_remove_column
method to inspect the arguments list and see what's going on. To do so, just run bundle open activerecord
and then explore to: lib/active_record/migration/command_recorder.rb:128.
这篇关于你如何使 remove_column 可逆?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!