连接 table 中的 ActiveRecord 自定义外键仅在一个方向上有效

ActiveRecord custom foreign key in the join table only works in one direction

Table name: bank_accounts        
  id              :integer          not null, primary key
  number          :string(255)
  ...

Table name: beneficiary_bank_accounts        
  id              :integer          not null, primary key
  beneficiary_id  :integer
  bene_bank_account_id :integer

Table name: beneficiaries   
  id         :integer          not null, primary key
  name       :string(255)
  ...
class BankAccount < ApplicationRecord
  
  has_many :beneficiary_bank_accounts, dependent: :destroy
  has_many :beneficiaries, through: :beneficiary_bank_accounts
  ...
end

class BeneficiaryBankAccount < ApplicationRecord
  
  belongs_to :beneficiary
  belongs_to :bene_bank_account, class_name: 'BankAccount', foreign_key: 'bene_bank_account_id'
  ...
end

class Beneficiary < ApplicationRecord

  has_many :beneficiary_bank_accounts, dependent: :destroy
  has_many :bene_bank_accounts, through: :beneficiary_bank_accounts, class_name: 'BankAccount'
  ...
end

BankAccountBeneficiary和[=21]之间存在一个has_many通过连接table的table之间的安排=] 作为联接 table.

与另一个定义发生名称冲突,需要重命名连接中的一个外键 table 以帮助 ActiveRecord 正确推断连接关系。

如您所见,在联接 table、BeneficiaryBankAccount 中,class_name 以及 bene_bank_account_id 列上的外键已被覆盖。

我 运行 遇到的问题是:

Beneficiary.last.bene_bank_accounts

生成正确的 sql

    SELECT bank_accounts.* 
    FROM bank_accounts 
    INNER JOIN beneficiary_bank_accounts ON bank_accounts.id = beneficiary_bank_accounts.bene_bank_account_id WHERE beneficiary_bank_accounts.beneficiary_id = 111 
    ORDER BY bank_accounts.title ASC

但是,从相反的方向来看,却不是。

BankAccount.last.beneficiaries

产生不正确的 sql 忽略 foreign_key 覆盖

    SELECT beneficiaries.* 
    FROM beneficiaries 
    INNER JOIN beneficiary_bank_accounts ON beneficiaries.id = beneficiary_bank_accounts.beneficiary_id 
    WHERE *beneficiary_bank_accounts.bank_account_id* = 135

我尝试将 foreign_key 添加到 BankAccount 模型中,如:

has_many :beneficiaries, through: :beneficiary_bank_accounts, foreign_key: 'bene_bank_account_id'

这没什么区别。

除了使用原始 SQL.

之外,我看不到在 BankAccount -> Beneficiary 方向上覆盖命名约定的方法

谁能纠正我的错误。

您应该可以通过指定关联的来源来执行此操作。

class BankAccount < ApplicationRecord
  ...
  has_many :bene_bank_accounts, through: :beneficiary_bank_accounts, class_name: 'BankAccount', source: :bene_bank_account

这样做的好处是您无需了解 BeneficiayBankAccount 如何与 BankAccount 建立关联的内部机制,您只需告诉 rails“使用现有的关联,无论它是什么”。 =11=]

看起来解决方案更简单。

必须将客户 foreign_key 添加到联接 table has_many 本身,如:

has_many :beneficiary_bank_accounts, dependent: :destroy, foreign_key: :bene_bank_account_id

class BankAccount < ApplicationRecord
  
  has_many :beneficiary_bank_accounts, dependent: :destroy, foreign_key: :bene_bank_account_id
  has_many :beneficiaries, through: :beneficiary_bank_accounts
  ...
end

现在两个方向都可以正常工作了。

感谢您的观看。