如何使用Rails 3样式迁移(def更改)识别迁移方向(向上或向下)?

sze*_*ryf 27 migration ruby-on-rails rails-migrations ruby-on-rails-3

我非常喜欢Rails 3样式的迁移,即一种change智能足以识别迁移是否正在安装或回滚的方法,因此我不必编写updown方法相互镜像.但我有一种情况,我需要在回滚迁移时跳过一些代码(更新counter_cache我正在添加的列).

我查看了http://guides.rubyonrails.org/migrations.html,但第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
Run Code Online (Sandbox Code Playgroud)

回滚此迁移时,fuzz不需要更新字段.有没有办法防止它?

我尝试过Product.column_names但是由于Rails足够智能以反向执行迁移,因此在删除列之前执行更新.此外,当change定义方法时,似乎忽略任何updown方法.还有其他想法吗?

Tim*_*ins 63

仅供将来参考,对于Rails 4,最好的方法是使用可逆:

def change
  # ...change code...

  reversible do |dir|
    dir.up do
      # ...up-only code...
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

请参阅http://guides.rubyonrails.org/migrations.html#using-reversible


Jor*_*ing 22

在这种情况下,我认为你将像往常一样使用updown方法.不要担心,尽管change在Rails 3中添加了这些方法,据我所知,这些方法并不适用于砧板.必要时继续使用它们.

编辑:这是一个选项:覆盖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
Run Code Online (Sandbox Code Playgroud)

思考?

  • @szeryf看看我更新的答案.希望这对你有用,我认为它应该是非常强大的`ActiveRecord :: Migration`的API. (2认同)

Fab*_*bio 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
Run Code Online (Sandbox Code Playgroud)

  • 所有上述建议中最干净的方法!它也适用于Rails 4.x. (2认同)