Search code examples
ruby-on-railsactiverecorddocker-composerails-activerecordsti

Using STI fails to migrate database


Been working on this particular issue for a while and thought it was time to ask for help. I've had a look at the following links but no luck

PG undefinedtable error relation users does not exist

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

And my issue is somewhat similar to this https://github.com/rails/rails/issues/6470 but not exactly.

I have a class called type_tables which is the base class for the STI here is the schema for 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

Now, this type table is only a base class in my project and other types such as device_type, certificate_type etc inherit from it.

The model for type_table

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

The other device_type model

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

Now, here's the interesting bit, it only shows this behaviour the first time i,e when there is no existing table in my Postgres database. When I successfully create and migrate my application schema and when the tables are present this line will work everytime.

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

My idea is that since it tries to find the column in the type_tables relation and the relation doesn't exist it throws a no relation exists error. Although the error you see on the console is

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)

When I create the db manually using

docker-compose run api rake db:create

And then run docker-compose up I get

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

NOTE: I know the work around and have my app working but I have a dependancy on a particular branch which has all of the commented code required to build my db for the first time which I want to remove.

Any help appreciated and thanks in advance.


Solution

  • It's a very bad idea to access your database while loading model definitions. Don't do that.

    Instead, consider using a class method that only retrieves the value the first time it's needed:

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

    Personally I'd strongly discourage even that much persistence -- better to spend one query retrieving it fresh for each request that needs it -- but that's more a matter of design judgement.