Ruby on rails 如何通过Rails 3风格的迁移(def更改)识别迁移方向(向上或向下)?
我真的很喜欢Rails 3风格的迁移,即一个Ruby on rails 如何通过Rails 3风格的迁移(def更改)识别迁移方向(向上或向下)?,ruby-on-rails,ruby-on-rails-3,migration,rails-migrations,Ruby On Rails,Ruby On Rails 3,Migration,Rails Migrations,我真的很喜欢Rails 3风格的迁移,即一个change方法足够智能,可以识别迁移是否正在安装或回滚,因此我不必编写up和down方法来相互镜像。但我有这样一种情况,当迁移回滚时,我需要跳过一些代码(更新我正在添加的counter\u cache列) 我看了一下,但第5节末尾的例子也有同样的问题: class AddFuzzToProduct < ActiveRecord::Migration class Product < ActiveRecord::Base end
change
方法足够智能,可以识别迁移是否正在安装或回滚,因此我不必编写up
和down
方法来相互镜像。但我有这样一种情况,当迁移回滚时,我需要跳过一些代码(更新我正在添加的counter\u cache
列)
我看了一下,但第5节末尾的例子也有同样的问题:
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
class AddFuzzToProduct'fuzzy'}
结束
结束
回滚此迁移时,不需要更新fuzz
字段。有什么办法可以预防吗
我试着查看
Product.column\u names
,但由于Rails足够聪明,可以执行反向迁移,所以更新是在删除列之前执行的。此外,当定义了change
方法时,任何up
或down
方法似乎都会被忽略。还有其他想法吗?在这种情况下,我认为您必须像往常一样使用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
class AddFuzzToProduct'fuzzy'}
结束
结束
结束
想法?这里有一个讨厌的想法:
@connection
是下潜时的命令记录器
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的范围内,因此它可能随时中断
如果只有更改方法具有确定迁移方向的合法方法…仅供将来参考,那么对于Rails 4来说,最好的方法是使用可逆:
def change
# ...change code...
reversible do |dir|
dir.up do
# ...up-only code...
end
end
end
请参见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
class AddFuzzToProduct'fuzzy'}
结束
结束
结束
我知道我可以定义向上
和向下
而不是更改
,但如果可能的话,我更喜欢使用更改
,因为这样可以减少重复。但如果没有其他选择,我想我将不得不使用它们:(@szeryf看一下我更新的答案。希望这对你有用,而且我认为它对于ActiveRecord::Migration
的API应该非常健壮。这对我来说非常有效;谢谢!在我的情况下,我必须使用一些SQL魔法来根据现有数据将数据插入表中。这样做太耗时了对具有大量记录的现有生产数据执行代码中的操作。可能的话,您可能只需要进行两次迁移?这是所有上述建议中最干净的方法!它也适用于Rails 4.x。并非所有版本的Rails都不推荐使用up和down方法,它们需要这样做。这里提供的所有解决方案都不好因为它们不会被遗忘,而且有难闻的气味,解决问题的最好方法就是写下正确的上下方法