我非常喜欢Rails 3样式的迁移,即一个change
方法足够聪明,可以识别是否正在安装或回滚迁移,因此我不必编写up
和{ {1}}方法相互镜像。但我有一种情况,我需要在回滚迁移时跳过一些代码(更新我正在添加的down
列)。
我看了http://guides.rubyonrails.org/migrations.html,但第5节末尾的例子也遇到了同样的问题:
counter_cache
回滚此迁移时,不需要更新class AddFuzzToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :products, :fuzz, :string
Product.reset_column_information
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
字段。有没有办法防止它?
我尝试查看fuzz
但由于Rails足够聪明以反向执行迁移,因此在删除列之前执行更新。此外,在定义Product.column_names
方法时,似乎忽略了任何change
或up
方法。还有其他想法吗?
答案 0 :(得分:61)
仅供将来参考,对于Rails 4,最好的方法是使用可逆:
def change
# ...change code...
reversible do |dir|
dir.up do
# ...up-only code...
end
end
end
请参阅http://guides.rubyonrails.org/migrations.html#using-reversible
答案 1 :(得分:20)
在这种情况下,我认为您必须像往常一样使用up
和down
方法。不要担心,尽管在Rails 3中添加了change
,但据我所知,这些方法并不适用于斩波块。必要时继续使用它们。
修改:这是一个选项:覆盖migrate
。
class AddFuzzToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :products, :fuzz, :string
end
def migrate(direction)
super # Let Rails do its thing as usual...
if direction == :up # ...but then do something extra if we're going 'up.'
Product.reset_column_information
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
end
思想?
答案 2 :(得分:19)
在rails 3.x中你也可以这样做
class AddFuzzToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :products, :fuzz, :string
unless reverting?
# Do this only when direction is up
Product.reset_column_information
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
end
答案 3 :(得分:0)
这是一个令人讨厌的想法:@connection
是CommandRecorder,当它失败时。
def change
add_column :products, :fuzz, :string
unless @connection.kind_of?(ActiveRecord::Migration::CommandRecorder)
Product.reset_column_information
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
没试过。显然你不在Rails API之外,所以它可能随时都会中断。
如果只有改变方法有合法的方法来确定迁移方向......