Rails 7.0.6:注释所有Fixture仍触发外键约束违反错误
Rails测试外键错误排查与解决
问题概述
- 测试运行时抛出错误:
RuntimeError: Foreign key violations found in your fixture data. Ensure you aren't referring to labels that don't exist on associations. - 已注释所有Fixture文件,项目含4个模型(其中一个带Active Storage附件),所有表为空仍触发错误
- 已尝试重建测试数据库、重新执行迁移,问题未解决
- 最近代码变更:通过scaffold新增2个模型(其一带Active Storage附件)、修改某模型为自定义主键(该主键被另一模型引用)
Postgres日志(中文翻译)
2023-08-13 20:26:45.959 CEST [3596] ERROR: 权限拒绝:"RI_ConstraintTrigger_c_41320" 是系统触发器 2023-08-13 20:26:45.959 CEST [3596] STATEMENT: ALTER TABLE "active_storage_variant_records" DISABLE TRIGGER ALL;ALTER TABLE "disbursements" DISABLE TRIGGER ALL;ALTER TABLE "merchants" DISABLE TRIGGER ALL;ALTER TABLE "merchants_files" DISABLE TRIGGER ALL;ALTER TABLE "orders" DISABLE TRIGGER ALL;ALTER TABLE "active_storage_blobs" DISABLE TRIGGER ALL;ALTER TABLE "active_storage_attachments" DISABLE TRIGGER ALL;ALTER TABLE "schema_migrations" DISABLE TRIGGER ALL;ALTER TABLE "ar_internal_metadata" DISABLE TRIGGER ALL 2023-08-13 20:26:45.963 CEST [3596] ERROR: 权限拒绝:"RI_ConstraintTrigger_c_41320" 是系统触发器 2023-08-13 20:26:45.963 CEST [3596] STATEMENT: ALTER TABLE "active_storage_variant_records" ENABLE TRIGGER ALL;ALTER TABLE "disbursements" ENABLE TRIGGER ALL;ALTER TABLE "merchants" ENABLE TRIGGER ALL;ALTER TABLE "merchants_files" ENABLE TRIGGER ALL;ALTER TABLE "orders" ENABLE TRIGGER ALL;ALTER TABLE "active_storage_blobs" ENABLE TRIGGER ALL;ALTER TABLE "active_storage_attachments" ENABLE TRIGGER ALL;ALTER TABLE "schema_migrations" ENABLE TRIGGER ALL;ALTER TABLE "ar_internal_metadata" ENABLE TRIGGER ALL 2023-08-13 20:26:45.966 CEST [3596] ERROR: 表 pg_constraint 权限拒绝 2023-08-13 20:26:45.966 CEST [3596] CONTEXT: SQL语句 "UPDATE pg_constraint SET convalidated=false WHERE conname = 'fk_rails_c3b3935057' AND connamespace::regnamespace = 'public'::regnamespace; ALTER TABLE public.active_storage_attachments VALIDATE CONSTRAINT fk_rails_c3b3935057;" PL/pgSQL函数 inline_code_block 第16行 EXECUTE处 2023-08-13 20:26:45.966 CEST [3596] STATEMENT: do $$ declare r record; BEGIN FOR r IN ( SELECT FORMAT( 'UPDATE pg_constraint SET convalidated=false WHERE conname = ''%I'' AND connamespace::regnamespace = ''%I''::regnamespace; ALTER TABLE %I.%I VALIDATE CONSTRAINT %I;', constraint_name, table_schema, table_schema, table_name, constraint_name ) AS constraint_check FROM information_schema.table_constraints WHERE constraint_type = 'FOREIGN KEY' ) LOOP EXECUTE (r.constraint_check); END LOOP; END; $$;
解决步骤
1. 修复数据库用户权限
日志明确显示测试数据库用户无操作系统触发器和pg_constraint表的权限,执行以下操作:
- 登录Postgres超级用户(如postgres),运行SQL:
GRANT ALL PRIVILEGES ON DATABASE your_test_db_name TO your_app_user; GRANT ALL ON SCHEMA public TO your_app_user; GRANT ALL ON ALL TABLES IN SCHEMA public TO your_app_user; GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO your_app_user; - 本地开发环境可直接修改
config/database.yml,将测试库用户名改为postgres(超级用户),避免权限问题。
2. 检查自定义主键的外键关联
修改模型为自定义主键后,需确保关联字段完全匹配:
- 确认关联模型的外键字段类型与自定义主键类型一致(比如主键是字符串,外键不能用默认的bigint),检查迁移文件是否明确指定类型。
- 回滚并重新执行迁移:
rails db:rollback STEP=2 # 回滚到修改主键前的版本,步数按需调整 rails db:migrate rails db:test:prepare
3. 清理Active Storage关联残留
新增带Active Storage的模型后,可能存在无效约束:
- 检查
db/schema.rb中active_storage_attachments和active_storage_blobs的外键约束是否合法。 - 权限修复后仍有问题,可手动删除无效约束:
ALTER TABLE active_storage_attachments DROP CONSTRAINT IF EXISTS fk_rails_c3b3935057;
4. 临时禁用测试外键校验
若以上步骤无效,可在测试环境临时禁用外键校验:
- 在
test/test_helper.rb中添加:class ActiveSupport::TestCase setup do ActiveRecord::Base.connection.disable_referential_integrity {} end end
内容的提问来源于stack exchange,提问作者Sergey Panov
相关产品推荐
相关产品推荐

