49

我正在使用 Rails 和 PostgreSQL,并且有一个基本的一对多关系,一个Auction有很多Bids。但是,当我尝试删除拍卖(存在出价)时,我收到以下错误:

错误:表“auctions”的更新或删除违反了表“bids”的外键约束“fk_rails_43e9021cbf”。详细信息:Key(id)=(1) 仍然从表“bids”中引用。

删除没有出价的拍卖不会出错。

让我感到困惑的是,在我的Auction模型中,我有:

has_many :bids, dependent: :destroy

错误屏幕截图(better_error gem)

既然我有一个依赖销毁子句,为什么我仍然收到这个错误?

编辑:我尝试删除整个数据库,然后重新创建/重新迁移所有内容 - 仍然得到相同的错误。

4

8 回答 8

45

Rails v4.2你可以这样做:

创建迁移以更新外键

20160321165946_update_foreign_key.rb

class UpdateForeignKey < ActiveRecord::Migration
  def change
    # remove the old foreign_key
    remove_foreign_key :posts, :users

    # add the new foreign_key
    add_foreign_key :posts, :users, on_delete: :cascade
  end
end
于 2016-03-21T17:15:06.310 回答
20

您是使用delete还是destroy移除这些对象?我认为您正在使用delete并且想要使用destroy

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Delete+or+destroy-3F

于 2015-03-11T21:24:52.413 回答
16

我的问题是我@auction.delete在尝试删除记录时正在使用(在我发布的屏幕截图中可见)。

删除将忽略我已有的任何回调。所以即使我有一个从属的destroy子句,它也没有被调用——因此Rails会抛出一个错误。如果/当我将代码更改为 read@auction.destroy时,回调被调用并解决了问题。

参考: 销毁和删除的区别

于 2015-09-24T00:00:57.970 回答
9

您是否偶然使用了偏执狂宝石或类似的东西?

如果你是bidsparanoid不是auctions,你可能会遇到这个错误。

这会发生,因为当 rails 执行时dependent: destroy,它会软删除出价,但它们实际上仍然存在于数据库中(它们只是deleted_at设置了列)。因此,外键约束将失败。

于 2015-09-23T21:21:55.633 回答
4

您的错误来自数据库而不是导轨。您需要先在您的应用程序中删除出价或更改数据库中的外键约束以级联删除

于 2015-03-11T20:38:25.597 回答
1

Marc Busqué 有一篇关于这个问题的非常好的文章可能会有所帮助。

“当 ActiveRecord 遇到外键违规时,它会引发 ActiveRecord::InvalidForeignKey 异常。即使在其文档中它只是说当记录无法插入或更新时引发它,因为它引用了不存在的记录,事实是它也用于我们感兴趣的案例。”

有了它和一个 rescue_from 我们可以添加到 ApplicationController 或控制器关注点:

rescue_from 'ActiveRecord::InvalidForeignKey' do
  # Flash and render, render API json error... whatever
end
于 2015-09-23T21:05:38.097 回答
0

其他答案很好,但不要提到有时你想留下依赖记录,但取消外键

class Post < ActiveRecord::Base
  has_many :comments, dependent: :nullify
end

请注意,这将需要确保数据库表中的外键列具有 null: true

我不是肯定的,但您可能还需要添加optional: true到依赖模型中定义的关联关联。

于 2020-08-04T18:41:53.470 回答
-2

一个非常简单的解释:关联表包含至少 1 条记录,该记录连接到您要销毁的表中的记录。

要解决此问题,请添加dependent: :destroy(假设用户 has_many Posts)

has_many :post, dependent: :destroy
于 2020-09-10T03:35:52.530 回答