我想将类型为enum的属性“original_price_period”添加到我的Listing模型中。为此,我将ActiveRecord::Enum与PostgreSQL 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'
答案 0 :(得分:0)
由于PG Enums在rails中本身不受支持,因此您的架构无法转储,因此用于创建测试数据库。您可以通过dumping your schema as sql解决此问题,而不是ruby。
但是,我建议不要这样做,因为合并sql转储可能是一个痛苦的过程。或者,我建议只为您的枚举使用整数列而不是本机枚举类型。有两种方法可以转储架构。这是设置的 config.active_record.schema_format配置/ application.rb 设置,可以是:sql或:ruby。
答案 1 :(得分:0)
答案在这里找到:https://stackoverflow.com/a/45430348/3201684
基本上,新类型不属于ActionRecord的有效类型,因此在迁移运行时会被拒绝。作为一种变通方法,添加了初始化程序,包括新类型作为有效类型。