Je faisais ce genre de chose dans mes migrations:
add_column :statuses, :hold_reason, :string rescue puts "column already added"
mais il s'avère que, alors que cela fonctionne pour SQLite, cela ne fonctionne pas pour PostgreSQL. Il semble que si add_column explose, même si l'exception est interceptée la transaction est morte et donc la migration ne peut pas faire de travail supplémentaire.
Existe-t-il des moyens non spécifiques à la base de données pour vérifier si une colonne ou une table existe déjà? À défaut, y a-t-il un moyen de faire fonctionner mon bloc de sauvetage?
À partir de Rails 3.0 et versions ultérieures, vous pouvez utiliser column_exists?
pour vérifier l'existence d'une colonne.
unless column_exists? :statuses, :hold_reason
add_column :statuses, :hold_reason, :string
end
Il y a aussi un table_exists?
, qui remonte à Rails 2.1.
Ou encore plus court
add_column :statuses, :hold_reason, :string unless column_exists? :statuses, :hold_reason
Pour Rails 2.X , vous pouvez vérifier l'existence de colonnes avec les éléments suivants:
columns("[table-name]").index {|col| col.name == "[column-name]"}
S'il renvoie nil, aucune colonne de ce type n'existe. S'il renvoie un Fixnum, la colonne existe. Naturellement, vous pouvez mettre des paramètres plus sélectifs entre les {...}
si vous souhaitez identifier une colonne par plus que son nom, par exemple:
{ |col| col.name == "foo" and col.sql_type == "tinyint(1)" and col.primary == nil }
(cette réponse a d'abord été publiée le Comment écrire des migrations conditionnelles dans des rails? )
add_column :statuses, :hold_reason, :string unless Status.column_names.include?("hold_reason")