Rails迁移:检查存在性并继续前进吗?


80

我在迁移中正在做这种事情:

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

但事实证明,尽管这适用于SQLite,但不适用于PostgreSQL。好像add_column崩溃了,即使捕获到异常,事务也已死,因此Migration无法做任何其他工作。

是否有任何非DB专用方法来检查列或表是否已存在?失败了,有什么办法可以使我的营救真正发挥作用吗?


值得一提的是,由于在回滚阶段尚不知道正向迁移期间的条件,因此有条件迁移会导致回滚问题
oklas

仅做回滚中的非可选部分
Dan Rosenstark

Answers:


175

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

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

还有一个table_exists?功能,可以追溯到Rails 2.1。


在添加/创建列/表之前检查它是否被认为是最佳实践?(我当然知道这取决于手中的问题)
Aldo'xoen'Giambelluca 2014年

4
如果我在change方法中定义回滚,是否可以使用回滚?
dardub

1
是的,回滚将是一个问题...我们不确定是否应删除该列..因为我们没有记录以前的状态。
songyy

8

甚至更短

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

这将是对其他答案的评论,而不是答案。谢谢。
Dan Rosenstark

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 }

(此答案首先发布于“如何在Rails中编写条件迁移?”


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.