Rails 外键违规删除具有 dependent destroy 关系的 has_many 关系

3

我有一个在Rails 4.2模型中简单的has_many关系:

class Owner < ActiveRecord::Base
  has_many :nested_things, :inverse_of => :owner, :class_name => "Nested::Thing", :dependent => :destroy
end

class Nested::Thing < ActiveRecord::Base
  belongs_to :owner, :inverse_of=>:nested_things
end

这些模型比这复杂得多,并涉及许多其他关系。

今天有人试图删除一个所有者(Owner),但是失败了,因为在nested_things表上存在外键:

> psql annoying_problem

psql (9.5.3)
Type "help" for help.

annoying_problem=# \d+ nested_things
                                                            Table "public.nested_things"
      Column      |            Type             |                           Modifiers                            | Storage  | Stats target | Description 
------------------+-----------------------------+----------------------------------------------------------------+----------+--------------+-------------
 id               | integer                     | not null default nextval('nested_things_id_seq'::regclass)     | plain    |              | 
 owner_id         | integer                     |                                                                | plain    |              | 

 Indexes:
    "nested_things_pkey" PRIMARY KEY, btree (id)
    "ix_nested_things_on_owner_id" btree (owner_id)
Foreign-key constraints:
    "nested_things_owner_id_fk" FOREIGN KEY (owner_id) REFERENCES owners(id)

当删除所有者时,这是一个耗时的过程——在本地,该特定记录生成了一个包含所有执行的SQL的109,000行日志文件。但是,嵌套事物关系导致整个操作中止,因为失败了外键检查。
以下是日志文件中似乎相关的部分:
> grep -n nested_things delete-owner.txt 

....

109762: SQL (1.1ms)  DELETE FROM "nested_things" WHERE "nested_things"."id" = $1  [["id", 8665]]

109836: ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: 
        ERROR:  update or delete on table "owners" violates foreign key 
        constraint "nested_things_owner_id_fk" on table "nested_things"

109837: DETAIL:  Key (id)=(6343) is still referenced from table "nested_things".

这个所有者只有一个嵌套的条目。在Rails中,什么会导致 :dependent => :destroy 关系删除依赖关系,但失败于外键检查?


我原以为可能是索引损坏了,但重新建立索引并没有改变任何东西。 - John Naegle
当我尝试直接从表中删除时,这不是第一个被检查的外键。 - John Naegle
删除另一个也有嵌套事物的所有者记录完全没有问题。 - John Naegle
1个回答

1
结果表明,销毁操作中未考虑到has_many关系上的默认范围。

你是如何解决它的?是移除了default_scope,还是采用了其他方法解决的? - x'ES
看起来我在发生外键冲突的模型中添加了一个before_destroy,它删除了默认作用域中不存在的对象。 默认作用域是enabled:true,因此我的before_destroy删除了所有启用为false或启用为nil的内容:before_destroy { NestedThings.unscoped.where(:owner_id => self.id, :enabled => [nil, false]).destroy_all } - John Naegle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接