使用STI无法迁移数据库

时间:2018-08-07 02:59:14

标签: ruby-on-rails activerecord docker-compose rails-activerecord sti

在这个特定问题上工作了一段时间后,认为是时候寻求帮助了。我看过以下链接,但没有运气

PG undefinedtable error relation users does not exist

https://github.com/rails/rails/issues/3279

我的问题与此https://github.com/rails/rails/issues/6470有点相似,但不完全相同。

我有一个名为type_tables的类,它是STI的基类,这是STI的架构

create_table "type_tables", force: :cascade do |t|
 t.string "title"
 t.string "desc"
 t.string "type"
 t.string "uom"
 t.index ["title"], name: "index_type_tables_on_title"
 t.index ["type"], name: "index_type_tables_on_type"
end

现在,此类型表仅是我项目中的基类,其他类型(例如device_type,certificate_type等)也将从其继承。

type_table的模型

class TypeTable < ApplicationRecord
  validates :title, presence: true, uniqueness: true
end

另一个device_type模型

class DeviceType < TypeTable
  has_many :certificates
  #this is where the error originates
  GARMIN_ID = find_by(title: "Garmin").id

  #when i use some constant value rails successfully executes the 
   db:create task in my rake file
  GARMIN_ID = 22

end

现在,这是一个有趣的地方,它仅在我的Postgres数据库中没有现有表时才第一次显示此行为。当我成功创建和迁移我的应用程序架构时,以及当表存在时,此行将始终可用。

GARMIN_ID = find_by(title: "Garmin").id

我的想法是,由于它尝试在type_tables关系中查找该列并且该关系不存在,因此会引发不存在关系的错误。尽管您在控制台上看到的错误是

2018-08-07 02:24:49.281 UTC [69] FATAL:  database "myappdb" does not 
exist

mlcot_api | /usr/local/bundle/gems/activerecord-5.1.3/lib/active_record/connection_adapters/postgresql_adapter.rb:699:in 
`rescue in connect': FATAL:  database "myappdb" does not exist 
(ActiveRecord::NoDatabaseError)

当我使用

手动创建数据库时
docker-compose run api rake db:create

然后运行docker-compose up我得到

ERROR:  relation "type_tables" does not exist at character 566

/usr/local/bundle/gems/activerecord- `async_exec': PG::UndefinedTable: 
ERROR:  relation "type_tables" does not exist 
           (ActiveRecord::StatementInvalid)
           WHERE a.attrelid = '"type_tables"'::regclass

注意:我知道解决方法,可以运行我的应用程序,但是我依赖于包含所有注释代码的特定分支 第一次要删除我的数据库时需要。

任何帮助表示感谢,并提前致谢。

1 个答案:

答案 0 :(得分:0)

在加载模型定义时访问数据库是一个非常糟糕的主意。不要那样做。

相反,请考虑使用仅在首次需要时才检索值的类方法:

def self.garmin_id
  @garmin_id ||= find_by(title: "Garmin").id
end

我个人甚至强烈不建议这么持久化-最好花一个查询为每个需要它的请求重新获取它-但这更多是设计判断的问题。