【问题标题】:Rails Foreign Key violation deleting has_many relationships with dependent destroyRails外键违规删除has_many与依赖销毁的关系
【发布时间】:2017-01-21 12:18:16
【问题描述】:

我在 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)

owner 被删除时,这是一个耗时的过程——在本地,这条特定记录会生成一个包含所有执行 SQL 的 109,000 行日志文件。但是,nested_things 关系会导致整个操作中止,因为外键检查失败

这似乎是日志文件的相关部分:

> 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".

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

【问题讨论】:

  • 我认为索引可能已损坏,但重新索引并没有改变任何内容。
  • 这不是我尝试直接从表中删除时检查的第一个外键。
  • 删除另一个也有 nested_things 的所有者记录就可以了。

标签: ruby-on-rails postgresql activerecord postgresql-9.5


【解决方案1】:

原来答案是 has_many 关系的默认范围,而在销毁中没有考虑。

【讨论】:

  • 你是如何消除它的?您是否删除了 default_scope,或者以其他方式解决了它?
  • 看起来我在发生外键违规的模型中添加了一个 before_destroy,删除了默认范围内不存在的对象。默认范围是enabled: true,所以我的 before_destroy 删除了所有启用 false 或启用 nil 的内容:before_destroy { NestedThings.unscoped.where(:owner_id =&gt; self.id, :enabled =&gt; [nil, false]).destroy_all }
猜你喜欢
  • 2015-06-01
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-03
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多