Міграції рейок: перевірити існування та продовжувати рух?


80

Я робив такі речі в міграціях:

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

але виявляється, що, хоча це працює для SQLite, воно не працює для PostgreSQL . Здається, якщо add_column підірветься, навіть якщо буде вилучено виняток, транзакція мертва, і тому перенесення не може виконати жодної додаткової роботи.

Чи існують якісь окремі способи перевірки, чи вже існують стовпець або таблиця? Якщо цього не вдасться, чи є спосіб досягти того, щоб мій рятувальний блок справді працював?


Слід зазначити, що умовна міграція призводить до проблем із відкатом через те, що на етапі відкоту невідомо, які умови були під час прямої міграції
оклас

Тільки необов’язкову частину виконуйте у відкаті
Ден Розенстарк

Відповіді:


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

4
Чи працює це з відкатами, якщо я визначаю це в методі зміни?
дардуб,

1
Так, відкат був би проблемою ... ми не впевнені, чи слід видаляти стовпець чи ні .. оскільки ми не записуємо попередній стан.
songyy

8

Або навіть коротше

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

це був би коментар до іншої відповіді, а не відповіді. Дякую.
Ден Розенстарк,

4

Для Rails 2.X можна перевірити наявність стовпців наступним чином:

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

Якщо він повертає нуль, такого стовпця не існує. Якщо він повертає Fixnum, то стовпець справді існує. Звичайно, ви можете помістити більш вибіркові параметри між, {...}якщо ви хочете ідентифікувати стовпець не лише за його назвою, наприклад:

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

(ця відповідь вперше розміщена на Як записати умовні міграції в рейки? )


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.