Рельсы миграции: проверить существование и продолжать идти?


Я делал такие вещи в моих миграциях:

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

но оказывается, что,хотя это работает для SQLite, он не работает для PostgreSQL. Кажется, что если add_column взрывается,даже если исключение перехватывается, транзакция мертва, и поэтому миграция не может выполнять никакой дополнительной работы.

есть non-DB sepecific способы проверить, если столбец или таблица уже существуют? В противном случае, есть ли способ чтобы мой спасательный блок действительно работал?

4 61

4 ответа:

начиная с Rails 3.0 и более поздних версий, вы можете использовать column_exists? для проверки наличия столбца.

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

есть еще table_exists? функция, которая идет еще до рельсов 2.1.

или еще короче

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

на рельсы 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")