Vérifier si une table existe dans Rails

174

J'ai une tâche de râteau qui ne fonctionnera que si une table existe. Je travaille avec plus de 20 ingénieurs sur un site Web, je veux donc m'assurer qu'ils ont migré la table avant de pouvoir effectuer une tâche de râteau qui alimentera cette table respective.

AR a-t-il une méthode telle que Table.exists? Comment puis-je m'assurer que la migration de la table a réussi?

alorsengah
la source
12
La blague va ... combien d'ingénieurs faut-il pour migrer une table :)
Zabba
1
En production 1. Sur la mise en scène des dizaines et plusieurs fois chacun.
thenengah
2
Ne serait-il pas plus simple d'exécuter les migrations au début de votre tâche de rake? Vous n'avez donc pas à vous soucier des tables manquantes.
raskhadafi
@raskhadafi: Notez que les tables manquantes vont vous poser un problème si vos config / initialiseurs les utilisent. (c'est-à-dire même rake db:migrateéchouera.)
ocodo

Réponses:

302

Dans Rails 5, l' API est devenue explicite concernant les tables / vues , collectivement sources de données .

# Tables and views
ActiveRecord::Base.connection.data_sources
ActiveRecord::Base.connection.data_source_exists? 'kittens'

# Tables
ActiveRecord::Base.connection.tables
ActiveRecord::Base.connection.table_exists? 'kittens'

# Views
ActiveRecord::Base.connection.views
ActiveRecord::Base.connection.view_exists? 'kittens'

Dans Rails 2, 3 et 4, l'API concerne les tables .

# Listing of all tables and views
ActiveRecord::Base.connection.tables

# Checks for existence of kittens table/view (Kitten model)
ActiveRecord::Base.connection.table_exists? 'kittens'

Obtenir l'état des migrations:

# Tells you all migrations run
ActiveRecord::Migrator.get_all_versions

# Tells you the current schema version
ActiveRecord::Migrator.current_version

Si vous avez besoin de plus d'API pour les migrations ou les métadonnées, consultez:

capitainepete
la source
4
ActiveRecord::Base.connection.table_exist 'users'vérifierait une table d'utilisateurs.
thenengah
4
ActiveRecord::Base.connection.table_exists? 'kittensvérifierait une table Kitten. Sauf si j'ai détruit tous les chatons! drop_table :kittens
thenengah
1
Merci les gars! Je viens de l'utiliser.index_exists?('kittens', 'paws')
Voyage du
14
Cela fonctionne pour ActiveRecord 3.2.11 drop_table(:hosts_users) if table_exists? :hosts_users
Greg
1
ActiveRecord::Base.connection.data_source_exists? 'table_name'est le bon maintenant
Dorian
57

même si la table n'existe pas:

modèle Kitten, kittens rails de table attendus 3:

Kitten.table_exists? # => faux

alexey_the_cat
la source
+ 1 Solution plus élégante. Fonctionne également si le modèle remplace le nom de la table.
Daniel Rikowski
1
Confirmer que cela fonctionne pour Rails 2.3.18-lts (testé avec une table présente, une manquante avant d'exécuter le script / la console)
iheggie
32

J'ai découvert cela pendant que j'essayais de supprimer une table via une migration:

drop_table :kittens if (table_exists? :kittens)
ActiveRecord::Migration.drop_table :kittens if (ActiveRecord::Base.connection.table_exists? :kittens)

fonctionne pour Rails 3.2

Ce formulaire plus simple sera disponible dans Rails 5:

drop_table :kittens, if_exists: true

Référence: https://github.com/rails/rails/pull/16366

Et voici le CHANGELOG de Rails 5 ActiveRecord :

Introduisez l'option: if_exists pour drop_table.

Exemple:

drop_table(:posts, if_exists: true)

Cela exécuterait:

DROP TABLE IF EXISTS posts

Si la table n'existe pas, if_exists: false (la valeur par défaut) lève une exception tandis que if_exists: true ne fait rien.

kangkyu
la source
Cela échouera si la table est en fait une vue, car la table semblera exister, mais DROP TABLE ne peut pas la supprimer.
mcr
8

Rails 5.1

if ActiveRecord::Base.connection.data_source_exists? 'table_name'
   drop_table :table_name
end

ou

drop_table :table_name, if_exists: true
Vitor Oliveira
la source
2
table_exists fonctionne toujours dans rails-5, mais son comportement changera pour ne vérifier que les tables. Depuis la version 5.0.1, il vérifie les vues et les tables. data_source_exists conserve ce comportement et table_exists changera pour vérifier uniquement les tables.
John Naegle
Il ne demande pas à vérifier le tableau sur une migration, il doit être sûr que le tableau existe sur une tâche de râteau
Juan Furattini
0

La bonne façon de faire est Model.table_exists?

class Dog < ApplicationRecord
  # something
end

do_something if Dog.table_exists?
Juan Furattini
la source