【问题标题】:Check if a table exists in Rails检查Rails中是否存在表
【发布时间】:2011-09-29 05:25:54
【问题描述】:

我有一个 rake 任务,除非存在表,否则它将无法工作。我在一个网站上与 20 多位工程师合作,所以我想确保他们在执行将填充相应表的 rake 任务之前已经迁移了表。

AR有没有Table.exists之类的方法?如何确保他们已成功迁移表?

【问题讨论】:

  • 开个玩笑.. 迁移一张表需要多少工程师 :)
  • 在生产 1. 在 Staging 几十次和多次。
  • 在 rake 任务开始时运行迁移不是更容易吗?所以您不必担心缺少表格。
  • @raskhadafi :请注意,如果您的配置/初始化程序使用它们,丢失的表会给您带来问题。 (即即使rake db:migrate 也会失败。)

标签: ruby-on-rails ruby rails-activerecord rails-migrations


【解决方案1】:

在 Rails 5 中,API became explicit regarding tables/views,统称为数据源

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

在 Rails 2、3 和 4 中,API 是关于 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'

获取迁移状态:

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

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

如果您需要更多用于迁移或元数据的 API,请参阅:

【讨论】:

  • ActiveRecord::Base.connection.table_exist 'users' 将检查用户表。
  • ActiveRecord::Base.connection.table_exists? 'kittens 将检查 Kitten 表。那是除非我把所有的小猫都毁了! drop_table :kittens
  • 谢谢大家!我刚用.index_exists?('kittens', 'paws')
  • 这适用于 ActiveRecord 3.2.11 drop_table(:hosts_users) if table_exists? :hosts_users
  • ActiveRecord::Base.connection.data_source_exists? 'table_name' 现在是正确的
【解决方案2】:

即使表不存在:

型号Kitten,预期表kittens 轨道 3:

Kitten.table_exists? #=> 错误

【讨论】:

  • + 1 更优雅的解决方案。如果模型覆盖表名,也可以使用。
  • 确认这适用于 Rails 2.3.18-lts(测试存在一张表,在运行脚本/控制台之前缺少一张)
【解决方案3】:

我在尝试通过迁移删除表时发现了这一点:

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

适用于 Rails 3.2

这种更简单的形式将在 Rails 5 中可用:

drop_table :kittens, if_exists: true

参考:https://github.com/rails/rails/pull/16366

这是 Rails 5 ActiveRecord 的CHANGELOG

为 drop_table 引入 :if_exists 选项。

例子:

drop_table(:posts, if_exists: true)

这将执行:

DROP TABLE IF EXISTS posts

如果表不存在,if_exists: false(默认)会引发异常,而 if_exists: true 什么也不做。

【讨论】:

  • 如果该表实际上是一个视图,这将失败,因为该表似乎存在,但 DROP TABLE 不能删除它。
【解决方案4】:

Rails 5.1

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

drop_table :table_name, if_exists: true

【讨论】:

  • table_exists 在 rails-5 中仍然有效,但其行为将更改为仅检查表。从 5.0.1 开始,它会检查视图和表格。 data_source_exists 保持这种行为,table_exists 将更改为仅检查表。
  • 他不是要求在迁移时检查表,他需要确保表存在于 rake 任务中
【解决方案5】:

执行此操作的正确方法是 Model.table_exists?

class Dog < ApplicationRecord
  # something
end

do_something if Dog.table_exists?

【讨论】:

    猜你喜欢
    • 2011-02-20
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 2012-09-03
    相关资源
    最近更新 更多