如何使用 Rails 3 风格的迁移(定义更改)识别迁移方向(向上或向下)?

发布于 2024-12-08 19:23:07 字数 868 浏览 0 评论 0原文

我真的很喜欢 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

当此迁移回滚时,不需要更新 fuzz 字段。有办法预防吗?

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

I really like the Rails 3 style migrations, i.e. one change method being smart enough to recognize if the migrations is being installed or rolled back, so I don't have to write up and down methods mirroring each other. But I have situation that I need to skip some code when the migration is rolled back (updating counter_cache columns that I'm adding).

I looked at http://guides.rubyonrails.org/migrations.html but the examples at the end of section 5 suffer from the same problem:

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

When this migration is rolled back, the update of fuzz field is unnecessary. Is there a way to prevent it?

I tried looking into Product.column_names but since Rails is smart enough to perform migration in reverse direction, the update is executed before the column is removed. Also, when change method is defined, any up or down methods seem to be ignored. Any other ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

却一份温柔 2024-12-15 19:23:07

仅供将来参考,对于 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

Just for future reference, for Rails 4 the best way to do this is to use reversible:

def change
  # ...change code...

  reversible do |dir|
    dir.up do
      # ...up-only code...
    end
  end
end

See http://guides.rubyonrails.org/migrations.html#using-reversible

一桥轻雨一伞开 2024-12-15 19:23:07

在 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

In rails 3.x you can also do this

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
梦情居士 2024-12-15 19:23:07

在这种情况下,我认为您必须像往常一样使用 updown 方法。别担心,尽管 Rails 3 中添加了 change,但据我所知,这些方法并不会被淘汰。必要时继续使用它们。

编辑:这里有一个选项:覆盖迁移

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

想法?

In this case I think you'll have to use up and down methods as usual. Don't worry, despite the addition of change in Rails 3 those methods aren't, as far as I know, bound for the chopping block. Continue using them where necessary.

Edit: Here's an option: Override 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

Thoughts?

乜一 2024-12-15 19:23:07

这里有一个令人讨厌的想法:@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 之外,因此它随时可能会崩溃。

如果改变方法有一个合法的方法来确定迁移方向......

Here's a nasty thought: @connection is the CommandRecorder when going down.

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

Haven't tried it. Obviously you're outside the Rails API so it could break at any time.

If only the change method had a legitimate way of determining the migration direction...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文