新创建的枚举属性抛出PG :: UndefinedTable:错误:关系“table_name”不存在

时间:2017-11-30 17:47:45

标签: ruby-on-rails postgresql rspec enums rspec-rails

我想将类型为enum的属性“original_price_period”添加到我的Listing模型中。为此,我将ActiveRecord::EnumPostgreSQL enum type合并。

首先,我在列表中添加了以下迁移:

class AddRentableAndOriginalPricePeriodToListings < ActiveRecord::Migration
  def up
    execute <<-SQL
      CREATE TYPE original_price_period AS ENUM ('day', 'week', 'month');
    SQL

    add_column :listings, :original_price_period, :original_price_period
  end

  def down
    remove_column :listings, :original_price_period

    execute <<-SQL
      DROP TYPE original_price_period;
    SQL
  end
end

然后我在清单模型中添加了最近创建的枚举字段的声明:

listing.rb

class Listing < ActiveRecord::Base
  ...

  enum original_price_period: {
    day: 'day',
    week: 'week',
    month: 'month'
  }

  ...
end

显然,一切都很好。但是当我试图运行单元测试时,他们都被同样的信息打破了:

  ActiveRecord::StatementInvalid:
    PG::UndefinedTable: ERROR:  relation "listings" does not exist
    LINE 5:                WHERE a.attrelid = '"listings"'::regclass
                                              ^
    :               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 = '"listings"'::regclass
                     AND a.attnum > 0 AND NOT a.attisdropped
                   ORDER BY a.attnum
  # ./spec/models/listing_spec.rb:52:in `block (2 levels) in <top (required)>'
  # ./spec/models/listing_spec.rb:602:in `block (4 levels) in <top (required)>'
  # ./spec/support/database_cleaner.rb:9:in `block (3 levels) in <top (required)>'
  # ./spec/support/database_cleaner.rb:8:in `block (2 levels) in <top (required)>'
  # ------------------
  # --- Caused by: ---
  # PG::UndefinedTable:
  #   ERROR:  relation "listings" does not exist
  #   LINE 5:                WHERE a.attrelid = '"listings"'::regclass
  #                                             ^
  #   ./spec/models/listing_spec.rb:52:in `block (2 levels) in <top (required)>'

我正在使用Fabricators,并在某处读取它们可能在迁移之前运行,这导致测试失败。不过,我无法想办法解决这个问题。这是我到目前为止尝试失败的原因:

rake db:migrate RAILS_ENV=test
rake db:test:prepare
rake db:test:load

我真的不想重置或删除并创建我的数据库,所以请避免这些建议。也可以在这里添加spec_helper.rb,因为它可能是相关的:

spec_helper.rb

require 'simplecov'
require 'simplecov-json'
require 'simplecov-rcov'
require 'fantaskspec'

SimpleCov.formatters = [
    SimpleCov::Formatter::HTMLFormatter,
    SimpleCov::Formatter::JSONFormatter,
    SimpleCov::Formatter::RcovFormatter
]

SimpleCov.start
require 'webmock/rspec'

RSpec.configure do |config|
  # this fixes backtraces for me, it can be removed once this change is shipped: https://github.com/rspec/rspec-core/pull/1616
  config.backtrace_exclusion_patterns = [
    /(?-mix:(?-mix:\/lib\/rspec\/(core|mocks|expectations|support|matchers|rails|autorun)(\.rb|\/))|rubygems\/core_ext\/kernel_require\.rb)|(?-mix:\/libd*\/ruby\/)|(?-mix:org\/jruby\/)|(?-mix:\/bin\/)|(?-mix:\/gems\/)/
  ]

  config.infer_rake_task_specs_from_file_location!

  config.mock_with :rspec do |mocks|
    mocks.allow_message_expectations_on_nil = true
  end
end

更新

显然迁移失败,因此没有创建表“listing”。相反,db / schema.rb显示以下消息:

# Could not dump table "listings" because of following StandardError
#   Unknown type 'original_price_period' for column 'original_price_period'

2 个答案:

答案 0 :(得分:0)

由于PG Enums在rails中本身不受支持,因此您的架构无法转储,因此用于创建测试数据库。您可以通过dumping your schema as sql解决此问题,而不是ruby。

  

有两种方法可以转储架构。这是设置的   config.active_record.schema_format配置/ application.rb   设置,可以是:sql或:ruby。

但是,我建议不要这样做,因为合并sql转储可能是一个痛苦的过程。或者,我建议只为您的枚举使用整数列而不是本机枚举类型。

答案 1 :(得分:0)

答案在这里找到:https://stackoverflow.com/a/45430348/3201684

基本上,新类型不属于ActionRecord的有效类型,因此在迁移运行时会被拒绝。作为一种变通方法,添加了初始化程序,包括新类型作为有效类型。