ruby-on-railsrails-migrationsglobalize

Rails 5: db:migrate fails with globalize gem PG::UndefinedTable


I am trying to upgrade a Rails app from 4.2 to 5.1.

The gems I am currently using:

In my Gemfile:

gem 'globalize', git: 'https://github.com/globalize/globalize'
gem 'activemodel-serializers-xml'
gem 'globalize-accessors'
gem 'globalize3_helpers', git: 'https://github.com/mathieumahe/globalize3_helpers.git'

I have a migration file that looks like this:

class CreateQuotas < ActiveRecord::Migration[5.0]
  def change
    create_table :quotas do |t|
      t.references :survey, index: true
      t.integer :target, default: 0
      t.timestamps null: false
    end

    reversible do |dir|
      dir.up { Quota.create_translation_table!(title: :string) }
      dir.down { Quota.drop_translation_table! }
    end
  end
end

and the appropriate translations directive is set in the quota.rb model:

class Quota < ApplicationRecord
  # ...
  translates :title
  # ...
end

Running the migration is resulting in the following error:

rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::UndefinedTable: ERROR:  relation "quota" does not exist
LINE 8:                WHERE a.attrelid = '"quota"'::regclass
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
                     c.collname, col_description(a.attrelid, a.attnum) AS comment
                FROM pg_attribute a
                LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
                LEFT JOIN pg_type t ON a.atttypid = t.oid
                LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
               WHERE a.attrelid = '"quota"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum

Am I doing something incorrectly or did I miss something obvious?

UPDATE:

I've made some progress on this. I've input the SQL directly into the migration, so it looks something like this:

class CreateQuotas < ActiveRecord::Migration[5.0]
  def change
    create_table :quotas do |t|
      t.references :survey, index: true
      t.integer :target, default: 0
      t.timestamps null: false
    end

    reversible do |dir|
      dir.up do
        execute <<-SQL
          SELECT a.attname, format_type(a.atttypid, a.atttypmod),
               pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
               c.collname, col_description(a.attrelid, a.attnum) AS comment
          FROM pg_attribute a
          LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
          LEFT JOIN pg_type t ON a.atttypid = t.oid
          LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
         WHERE a.attrelid = '"quotas"'::regclass
           AND a.attnum > 0 AND NOT a.attisdropped
         ORDER BY a.attnum
        SQL
      end
      # dir.up do
      #   Quota.create_translation_table! :title => :string
      # end
      #
      dir.down do
        Quota.drop_translation_table!
      end
    end
  end
end

This seems to work.

Essentially, the Quota.create_translation_table! :title => :string directive is singularizing '"quota"'::regclass which causes the failure. It passes with '"quotas"'::regclass, which is not being inferred from the class name :/


Solution

  • After much head-scratching, I've realized what the issue is.

    Rails 4 allowed a singularized Quota model to be pluralized to quotas. Rails 5 singularizes Quotum and pluralizes it to quota.

    This explains the '"quota"'::regclass error, and why forcing it to '"quotas"'::regclass prevented the migration from failing.

    Renaming all models and migrations (Quota to Quotum and quotas to quota) fixes this issue in Rails 5.1.