我在迁移中正在做这种事情:
add_column :statuses, :hold_reason, :string rescue puts "column already added"
但事实证明,尽管这适用于SQLite,但不适用于PostgreSQL。好像add_column崩溃了,即使捕获到异常,事务也已死,因此Migration无法做任何其他工作。
是否有任何非DB专用方法来检查列或表是否已存在?失败了,有什么办法可以使我的营救真正发挥作用吗?
我在迁移中正在做这种事情:
add_column :statuses, :hold_reason, :string rescue puts "column already added"
但事实证明,尽管这适用于SQLite,但不适用于PostgreSQL。好像add_column崩溃了,即使捕获到异常,事务也已死,因此Migration无法做任何其他工作。
是否有任何非DB专用方法来检查列或表是否已存在?失败了,有什么办法可以使我的营救真正发挥作用吗?
Answers:
从Rails 3.0及更高版本开始,您可以使用column_exists?
检查列的存在。
unless column_exists? :statuses, :hold_reason
add_column :statuses, :hold_reason, :string
end
还有一个table_exists?
功能,可以追溯到Rails 2.1。
甚至更短
add_column :statuses, :hold_reason, :string unless column_exists? :statuses, :hold_reason
对于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中编写条件迁移?”)
add_column :statuses, :hold_reason, :string unless Status.column_names.include?("hold_reason")