首页 > 解决方案 > 您可以在从属::nullify 回调期间使用多个外键使 has_many、belongs_to 上的外键无效吗?

问题描述

我有一个这样的用户类:

class User < ApplicationRecord
  has_many :payments
end

和这样的付款类:

class Payment < ApplicationRecord
  belongs_to :buyer, class_name: 'User', foreign_key: 'buyer_id'
  belongs_to :seller, class_name: 'User', foreign_key: 'seller_id'
end

当我销毁用户时,我希望 Payment 中的外键为零,因此我dependent: :nullify向 User 模型添加了一个回调,如下所示:

class User < ApplicationRecord
  has_many :payments, foreign_key: "seller_id", class_name: 'Payment', dependent: :nullify
end

果然我的规范通过了:

seller.destroy
expect(payment.reload.seller).to be_nil # => true

当用户被销毁时,我希望 Payment 中的 purchase_id 也为零,因此我dependent: :nullify向 User 模型添加了另一个回调:

class User < ApplicationRecord
  has_many :payments, foreign_key: "buyer_id", class_name: 'Payment', dependent: :nullify
  has_many :payments, foreign_key: "seller_id", class_name: 'Payment', dependent: :nullify
end

但后来我的规范失败了:

buyer.destroy
expect(payment.reload.buyer).to be_nil

我收到此错误:PG::ForeignKeyViolation: ERROR: update or delete on table “xxx” violates foreign key constraint

我注意到 has_many在模型中最后定义的这两个关联中的任何一个都是通过的,而has_many首先定义的则失败。

标签: ruby-on-railspostgresql

解决方案


多亏了这个 SO answer,我通过迁移使两个测试都通过了,以便外键在数据库级别无效,而不是依赖回调。

def change
    remove_foreign_key :payments, :users, column: :buyer_id
    add_foreign_key :payments, :users, column: :buyer_id, on_delete: :nullify

    remove_foreign_key :payments, :users, column: :seller_id
    add_foreign_key :payments, :users, column: :seller_id, on_delete: :nullify
  end

推荐阅读