我在两个模型之间有以下关系:
class Transaction < ApplicationRecord
has_many :transfer_sources, dependent: :nullify, foreign_key: "transaction_source_id", class_name: "Transfer"
has_many :transfer_dests, dependent: :nullify, foreign_key: "transaction_dest_id", class_name: "Transfer"
...
end
class Transfer < ApplicationRecord
belongs_to :transaction_source, optional: true, class_name: "Transaction"
belongs_to :transaction_dest, optional: true, class_name: "Transaction"
...
end
因此,在
Transfer
记录中,如果设置了另一个,则 transaction_source
或 transaction_dest
可以为零,唯一无效的情况是将两者都设置为 nil。
如果两者均已设置并且我销毁了其中一项交易,那很好,并且我仍然希望传输存在,则引用将被清空。
但是如果我随后销毁其他相关事务,那么两个事务引用都将失效。
在这种情况下我想做的是,如果两个交易(源和目标)都变成零,则自动销毁传输记录。
我在 Transfer 上尝试了 after_update 回调,但是取消依赖关系似乎并没有将 Transfer 对象加载到内存中,它只是直接执行 UPDATE SQL 语句。
你可以尝试这样的事情:
class Transfer < ApplicationRecord
# ...
scope :with_single_transaction, lambda {
where(transaction_source_id: nil).or(where(transaction_dest_id: nil))
}
scope :related_to, lambda(transaction_id) {
where(transaction_source_id: transaction_id).or(where(transaction_dest_id: transaction_id))
}
# ...
end
class Transaction < ApplicationRecord
# ...
before_destroy do
::Transfer.with_single_transaction.related_to(transaction_id: id).destroy_all
end
# ...
end
before_destroy
回调被包装到数据库事务中。因此,如果删除 Transfer
在某个时刻出现错误,则删除相关的 Transaction
将被回滚。