用delete_all / delete删除rails活动记录违反了外键约束

问题描述 投票:0回答:2

我有一个与: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

并且它可以摧毁,所以我在做什么错呢?

谢谢/ [路易丝

ruby-on-rails activerecord associations cascading-deletes
2个回答
0
投票

您需要在迁移级别进行设置。

类似这样的东西:

create_table :childs do |t|
  t.references :parent, index: true, foreign_key: {on_delete: :cascade}
  t.string :name

  t.timestamps null: false
end

0
投票

在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, on_delete: :cascade
  end
end

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

has_many :inventory_items, dependent: :delete_all

同样也有效,并且是在像MySQL这样的农民数据库上的唯一选项,但是只有在您将模型声明为实现为模型回调的模型上调用.destroy而不是.delete时才会触发。例如:

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

store = Store.find(1)
store.destroy # triggers callbacks and will delete all assocatiated inventory_items
store.delete # will not trigger callbacks
© www.soinside.com 2019 - 2024. All rights reserved.