Verifique se existe uma tabela no Rails

174

Eu tenho uma tarefa de rake que não funcionará, a menos que exista uma tabela. Estou trabalhando com mais de 20 engenheiros em um site, por isso quero ter certeza de que eles migraram a tabela antes de poderem executar uma tarefa de rake que preencherá a respectiva tabela.

O AR tem um método como Table.exists? Como posso garantir que eles migraram a tabela com êxito?

thenengah
fonte
12
A piada vai .. quantos engenheiros leva para migrar uma mesa :)
Zabba
1
Na produção 1. Na preparação de dezenas e várias vezes cada.
thenengah
2
Não seria mais fácil apenas executar as migrações no início da sua tarefa de rake? Portanto, você não precisa se preocupar com a falta de tabelas.
raskhadafi 24/07/12
@raskhadafi: Observe que as tabelas ausentes darão um problema se as suas configurações / inicializadores as usarem. (ou seja, mesmo rake db:migrateirá falhar.)
ocodo

Respostas:

302

No Rails 5, a API tornou-se explícita em relação a tabelas / visualizações , fontes de dados coletivamente .

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

Nos Rails 2, 3 e 4, a API é sobre tabelas .

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

Obtendo o status das migrações:

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

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

Se você precisar de mais APIs para migrações ou metadados, consulte:

capitão
fonte
4
ActiveRecord::Base.connection.table_exist 'users'iria verificar uma tabela de usuários.
thenengah
4
ActiveRecord::Base.connection.table_exists? 'kittensiria procurar uma mesa Kitten. Isto é, a menos que eu destrua todos os gatinhos! drop_table :kittens
thenengah
1
Obrigado rapazes! Eu apenas usei.index_exists?('kittens', 'paws')
Viagem
14
Isso funciona para o ActiveRecord 3.2.11 drop_table(:hosts_users) if table_exists? :hosts_users
Greg
1
ActiveRecord::Base.connection.data_source_exists? 'table_name'é o correto agora
Dorian
57

mesmo que a tabela não exista:

modelo Kitten, kittens trilhos de tabela esperados 3:

Kitten.table_exists? # => false

alexey_the_cat
fonte
+ 1 Solução mais elegante. Também funciona se o modelo substituir o nome da tabela.
Daniel Rikowski
1
Confirmando isso funciona para Rails 2.3.18-lts (testado com uma tabela presente, um desaparecido antes de executar script / console)
iheggie
32

Descobri isso enquanto tentava remover uma tabela por meio de uma migração:

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

trabalha para o Rails 3.2

Este formulário mais simples estará disponível no Rails 5:

drop_table :kittens, if_exists: true

Referência: https://github.com/rails/rails/pull/16366

E aqui está o do Rails 5 ActiveRecord CHANGELOG :

Apresente a opção: if_exists para drop_table.

Exemplo:

drop_table(:posts, if_exists: true)

Isso executaria:

DROP TABLE IF EXISTS posts

Se a tabela não existir, if_exists: false (o padrão) gera uma exceção, enquanto if_exists: true não faz nada.

kangkyu
fonte
Isso falhará se a tabela for de fato uma exibição, pois a tabela parecerá existir, mas o DROP TABLE não poderá descartá-la.
mcr 29/03
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
fonte
2
table_exists ainda funciona no rails-5, mas seu comportamento será alterado para apenas verificar tabelas. A partir do 5.0.1, ele verifica visualizações e tabelas. data_source_exists mantém esse comportamento e table_exists mudará para apenas verificar tabelas.
John Naegle
Ele não está pedindo para verificar a tabela em uma migração, ele precisa ter certeza de que a tabela existe em uma tarefa de rake
Juan Furattini
0

A maneira correta de fazer isso é Model.table_exists?

class Dog < ApplicationRecord
  # something
end

do_something if Dog.table_exists?
Juan Furattini
fonte