5

我发现自己必须在 Rails 应用程序的几个表上执行非常相似的 sql 语句(除了表名之外可能还有 1 个参数)。结果,我得到了很多类似的迁移,比如这个:

class DoSomeSQLOnUser < ActiveRecord::Migration
  def up
    execute('some long sql that alters the user.field1')
    execute('some long sql that alters the user.field2')
  end

  def down
    execute('some sql that undoes the changes')
  end
end

然后我对客户、销售等也有同样的看法。

我想扩展ActiveRecord::Migration以便我可以这样做:

class DoSomeSQLOnUser < ActiveRecord::Migration
  def change
    do_custom_thing_on :users, :field1
    do_custom_thing_on :users, :field2
  end
end

我怎样才能做到这一点?我想我知道当操作分为上下时该怎么做,像这样:

class DoSomeSQLOnUser < ActiveRecord::Migration
  def up
    do_custom_thing_on :users, :field1
    do_custom_thing_on :users, :field2
  end
  def down
    undo_custom_thing_on :users, :field1
    undo_custom_thing_on :users, :field2
  end
end

但是这样做是为了让变化是“可逆的”,这让我无法理解。

4

4 回答 4

2

这似乎不是官方支持的方法,因此您可能需要打开类ActiveRecord::Migration::CommandRecorder并记录新方法及其反转版本。

在activerecord/lib/active_record/migration/command_recorder.rb中找到类的定义。

于 2013-06-07T11:52:44.693 回答
2

在 Rails 4 中有一个可逆的辅助方法,你可以像这样使用它:

def change
  do_custom_thing_on :users, :field1
  do_custom_thing_on :users, :field2
end

def do_custom_thing_on(table, field)
  reversible do |dir|
    dir.up { execute "some long sql to alter #{field} on #{table}"}
    dir.down { execute "some long sql to undo #{field} on #{table}"}
  end
end
于 2015-08-01T13:43:24.840 回答
1

不确定您是否需要做其他事情,但至少您应该向ActiveRecord::Migration::CommandRecorder添加一个 inverse_custom_thing 方法

于 2013-06-07T11:54:45.927 回答
0

更改方法的主要目的是添加、重命名列但不删除。更改方法“知道”在迁移回滚时如何进行反向操作。因此,如果您想做一些不删除的事情,只需在 change 方法中执行,我认为 ActiveRecord 会自行反转它。

您可以从官方文档中获得更多信息

于 2013-06-07T11:59:27.467 回答