Sprawdź, czy tabela istnieje w Railsach

174

Mam zadanie rake, które nie zadziała, jeśli nie ma stołu. Pracuję z ponad 20 inżynierami na stronie internetowej, więc chcę się upewnić, że dokonali migracji tabeli, zanim będą mogli wykonać zadanie prowizji, które zapełni tę odpowiednią tabelę.

Czy AR ma metodę taką jak Table.exists? Jak mogę się upewnić, że migracja tabeli zakończyła się pomyślnie?

thenengah
źródło
12
Żart mówi… ilu inżynierów potrzeba, aby zmigrować stół :)
Zabba
1
Na produkcji 1. Na inscenizacji dziesiątki i wiele razy.
thenengah,
2
Czy nie byłoby łatwiej po prostu uruchomić migracje na początku zadania rake? Nie musisz się więc martwić brakującymi stolikami.
raskhadafi
@raskhadafi: Zauważ, że brakujące tabele spowodują problem, jeśli twoja konfiguracja / inicjatory ich używają. (czyli nawet rake db:migratesię nie uda)
ocodo

Odpowiedzi:

302

W Railsach 5 API stało się jawne w odniesieniu do tabel / widoków , zbiorczych źródeł danych .

# 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'

W Railsach 2, 3 i 4 API dotyczy tabel .

# 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'

Uzyskanie statusu migracji:

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

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

Jeśli potrzebujesz więcej interfejsów API do migracji lub metadanych, zobacz:

kapitanie
źródło
4
ActiveRecord::Base.connection.table_exist 'users'sprawdziłby tabelę użytkowników.
thenengah,
4
ActiveRecord::Base.connection.table_exists? 'kittenssprawdziłby stolik Kitten. Chyba że zniszczyłem wszystkie kocięta! drop_table :kittens
thenengah,
1
Dzięki chłopaki! Właśnie użyłem.index_exists?('kittens', 'paws')
Trip
14
Działa to dla ActiveRecord 3.2.11 drop_table(:hosts_users) if table_exists? :hosts_users
Greg
1
ActiveRecord::Base.connection.data_source_exists? 'table_name'jest teraz poprawna
Dorian
57

nawet jeśli tabela nie istnieje:

model Kitten, oczekiwana tabelakittens szyny 3:

Kitten.table_exists? # => fałsz

alexey_the_cat
źródło
+ 1 Bardziej eleganckie rozwiązanie. Działa również, jeśli model zastępuje nazwę tabeli.
Daniel Rikowski
1
Potwierdzenie, że to działa dla Railsów 2.3.18-lts (testowane z jedną tabelą, jedną brakującą przed uruchomieniem skryptu / konsoli)
iheggie
32

Dowiedziałem się o tym podczas próby usunięcia tabeli poprzez migrację:

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

działa dla Railsów 3.2

Ta prostsza forma będzie dostępna w Railsach 5:

drop_table :kittens, if_exists: true

Źródła: https://github.com/rails/rails/pull/16366

A oto dziennik zmian Rails 5 ActiveRecord :

Wprowadź opcję: if_exists dla drop_table.

Przykład:

drop_table(:posts, if_exists: true)

To wykonałoby:

DROP TABLE IF EXISTS posts

Jeśli tabela nie istnieje, if_exists: false (wartość domyślna) zgłasza wyjątek, podczas gdy if_exists: true nic nie robi.

kangkyu
źródło
To się nie powiedzie, jeśli tabela jest w rzeczywistości widokiem, ponieważ wydaje się, że tabela istnieje, ale DROP TABLE nie może jej usunąć.
mcr
8

Szyny 5.1

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

lub

drop_table :table_name, if_exists: true
Vitor Oliveira
źródło
2
table_exists nadal działa w rails-5, ale jego zachowanie będzie się zmieniało tylko w celu sprawdzenia tabel. Od 5.0.1 sprawdza widoki i tabele. data_source_exists utrzymuje, że zachowanie i table_exists będą się zmieniać tylko na sprawdzanie tabel.
John Naegle,
Nie prosi o sprawdzenie stołu na migracji, musi mieć pewność, że stół istnieje na zadaniu rake
Juan Furattini.
0

Właściwy sposób na to to Model.table_exists?

class Dog < ApplicationRecord
  # something
end

do_something if Dog.table_exists?
Juan Furattini
źródło