在 Rails 迁移中使用 up/down 与 change/reversible 方法有什么不同吗?

Is there any difference in using up/down vs change/reversible methods in Rails migrations?

在 Rails 迁移中,如果我这样做有什么区别吗:

def up
  foo
end

def down
  bar
end

或者这个:

def change
  reversible do |direction|
    direction.up { foo }
    direction.down { bar }
  end
end

?

我觉得如果迁移的部分包含可逆的方法,比如create_tableadd_column等,还是用change方法比较好。除此之外,有什么区别吗?

如你所见,没有优势。主要优点是很多时候你根本不需要写 down 方法/块,例如

class SomeMigration < ActiveRecord::Migration
  def change
    create_table :articles do |t|
      ...
    end
  end
end

当 activerecord 不知道如何反转迁移的一小部分时(例如原始 SQL 语句),主要使用 reversible 方法

change 方法适用于许多可以轻松导出可逆逻辑并且 ActiveRecord 迁移可以轻松处理的情况。但是,在某些情况下,您可能需要在迁移中做一些特定的事情以确保它 运行 没有错误。也可能有一些复杂的东西是不可逆的迁移。 参见 Rails: Is it bad to have an irreversible migration?

在这种情况下,最好使用 up down 方法,但也无法检查当前的迁移方向是否只是 reverting?

这是一个示例,您可以使用它来代替 2 up/down 方法。在这个例子中,还有一个复杂的数据方法 not show 在没有条件逻辑的情况下导致迁移错误。我已经省略了,因为它与你的问题无关:

def change
  add_column :languages, :iso_639_2t, :string
  add_column :languages, :iso_639_2b, :string
  add_column :languages, :iso_639_3, :string
  add_index :languages, :iso_639_2t
  unless reverting?
    ActiveRecord::Base.connection
    .execute("ALTER SEQUENCE languages_id_seq RESTART WITH #{Language.count+1}")
  end
end

例如,如果通过 migration_data gem 在迁移中使用复杂的数据操作,您可能需要添加一个 def check_data 方法并在 data_check 失败时引发异常。

如果迁移确实不可逆(破坏数据),您可能还想使用 up/down 例如:

def up
  remove_column :signup, :date
end

def down
  raise ActiveRecord::IrreversibleMigration, "Date field dropped in previous migration. Data unrecoverable"
end