Rails迁移:检查存在并继续进行?

时间:2009-10-29 17:12:13

标签: ruby-on-rails migration

我在迁移过程中做过这样的事情:

add_column :statuses, :hold_reason, :string rescue puts "column already added"

但事实证明,虽然这适用于SQLite,但它不适用于PostgreSQL 。似乎add_column爆炸,即使捕获了异常,该事务已经死亡,因此迁移无法执行任何其他工作。

是否有非DB特定方法来检查列或表是否已存在?如果做不到的话,有没有办法让我的救援区真正起作用?

5 个答案:

答案 0 :(得分:154)

从Rails 3.0及更高版本开始,您可以使用column_exists?来检查列的存在。

unless column_exists? :statuses, :hold_reason
  add_column :statuses, :hold_reason, :string
end

还有一个table_exists?函数,可以追溯到Rails 2.1。

答案 1 :(得分:6)

甚至更短

add_column :statuses, :hold_reason, :string unless column_exists? :statuses, :hold_reason

答案 2 :(得分:4)

对于 Rails 2.X ,您可以使用以下内容检查列的存在:

columns("[table-name]").index {|col| col.name == "[column-name]"}

如果返回nil,则不存在此列。如果它返回Fixnum,则该列确实存在。当然,如果您想要通过多个名称来识别列,可以在{...}之间添加更多选择性参数,例如:

{ |col| col.name == "foo" and col.sql_type == "tinyint(1)" and col.primary == nil }

(此答案首先发布在How to write conditional migrations in rails?

答案 3 :(得分:2)

Rails 6.1+:

add_column :statuses, :hold_reason, :string, if_not_exists: true

https://github.com/rails/rails/pull/38352/files

Rails < 6.1:

add_column :statuses, :hold_reason, :string unless column_exists?(:statuses, :hold_reason)

答案 4 :(得分:1)

add_column :statuses, :hold_reason, :string unless Status.column_names.include?("hold_reason")