温馨提示:本文翻译自stackoverflow.com,查看原文请点击:activerecord - Deleting rails active records with delete_all/delete violates foreign key constraint
activerecord ruby-on-rails associations cascading-deletes

activerecord - 使用delete_all / delete删除Rails活动记录违反了外键约束

发布于 2020-03-29 21:34:54

我有一个与:dependent =>:destroy的活动记录关联设置,可按预期工作。然后我发现由于性能原因我需要使用delete而不是destroy,因此我根据关联将只是将destroy更改为delete_all / delete。

当我尝试删除时:

shop.shop_snapshots.completed.last.delete

我收到错误消息:

ActiveRecord::InvalidForeignKey (PG::ForeignKeyViolation: ERROR:  update or delete on table "shop_snapshots" violates foreign key constraint "fk_rails_c24b24adaf" on table "inventory_items"

但是为什么会这样-我相信我在快照上有正确的设置:

has_many :inventory_items, :dependent => :delete_all

它可以摧毁,所以我做错了什么?

谢谢/路易丝

查看更多

提问者
Lull
被浏览
122
max 2020-02-03 14:07

在Postgres上,您可以在外键本身上使用CASCADE选项。

CASCADE指定在删除引用的行时,引用该行的行也应自动删除。
- https://www.postgresql.org/docs/9.5/ddl-constraints.html

这通常是在创建表时设置的,但是您可以通过删除然后重新添加外键约束将其添加到现有表中:

class AddCascadeToOrderItems < ActiveRecord::Migration[6.0]
  def up
    remove_foreign_key :order_items, :orders
    add_foreign_key :order_items, :orders, on_delete: :cascade
  end

  def down
    remove_foreign_key :order_items, :orders
    add_foreign_key :order_items, :orders
  end
end

由于这是在数据库级别处理的,因此模型中不需要配置。

has_many :inventory_items, dependent: :delete_all

它也可以正常工作,并且在像MySQL这样的农民数据库上是唯一的选择,但是只有在您调用.destroy而不是.delete在将关联声明为作为模型回调实现的模型上才会触发它。例如:

class Store < ApplicationRecord
  has_many :inventory_items, dependent: :delete_all
end

store = Store.find(1)
store.destroy # triggers callbacks and will delete all assocatiated inventory_items
store.delete  # will not trigger callbacks