Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namespaced models causing UndefinedTable error

I have following namespaced models:

# app/models/face_data/pool_membership.rb
class FaceData::PoolMembership < ActiveRecord::Base
  self.table_name = 'face_data_pool_memberships'

  belongs_to :pool, class_name: 'FaceData::Pool'
  belongs_to :photo
end

# app/models/face_data/pool.rb
class FaceData::Pool < ActiveRecord::Base
  self.table_name = 'face_data_pools'
end

# app/models/photo.rb
class Photo < ActiveRecord::Base
  has_many :pool_memberships, class_name: 'FaceData::PoolMembership'
  has_many :pools, through: :pool_memberships, class_name: 'FaceData::Pool'
end

And database schema as following:

# db/schema.rb
create_table "face_data_pool_memberships", force: true do |t|
  # omitted
end

create_table "face_data_pools", force: true do |t|
  # omitted
end

The app is running fine but when booting (server, rake task etc.) I get the following error:

 PG::UndefinedTable: ERROR:  relation "pool_memberships" does not exist
 LINE 5:                WHERE a.attrelid = '"pool_memberships"'::regc...
 ^
 :               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
 pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
 FROM pg_attribute a LEFT JOIN pg_attrdef d
 ON a.attrelid = d.adrelid AND a.attnum = d.adnum
 WHERE a.attrelid = '"pool_memberships"'::regclass
 AND a.attnum > 0 AND NOT a.attisdropped
 ORDER BY a.attnum

It happens only in production (not in development environment) and looks like it does not have an effect in the runtime (app continues running fine - generated queries use correct table name).

Note that there are other FaceData namespaced modules and classes in the app. Setting table_name_prefix explicitly to an empty string does not make the error disappear.

My guess is that it has something to do with loading order of files or the has_many :through association. Any tips?

like image 387
Kreeki Avatar asked Dec 20 '22 16:12

Kreeki


1 Answers

To avoid all these problem you can do one thing. Create a app/models/face_data.rb with these contents

    module FaceData
      def self.table_name_prefix
        'face_data_'
      end
    end

With this, you are no more required to write self.table_name for each and every class you define within the same scope. In case you have any doubt do let me know.

like image 50
r3bo0t Avatar answered Jan 01 '23 16:01

r3bo0t