0
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

There exists a has_many through arrangement between 2 tables with a join table as shown above between BankAccount, Beneficiary with BeneficiaryBankAccount as the join table.

There was a name clash with another definition which required the renaming of one of a foreign key in the join table to help ActiveRecord infer the join relation correctly.

As you can see, in the join table, BeneficiaryBankAccount, the class_name has been overridden as well as the foreign key on the bene_bank_account_id column.

The problem I run into is that:

Beneficiary.last.bene_bank_accounts

produces the correct 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

But, from the opposite direction, it does not.

BankAccount.last.beneficiaries

produces the incorrect sql ignoring the foreign_key override

    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

I have tried adding the foreign_key to the BankAccount model, as in:

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

and this makes no difference.

I can't see a way of overriding the naming convention in the BankAccount -> Beneficiary direction short of using raw SQL.

Can anyone please put me right.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
willyab
  • 167
  • 1
  • 10
  • Does this answer your question? [Rails belongs\_to with custom column name](https://stackoverflow.com/questions/25047920/rails-belongs-to-with-custom-column-name) – Eyeslandic Sep 25 '20 at 09:26

2 Answers2

0

You should be able to do this by specifying the source of the association.

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

The advantage of this is you don't need to know the internals of how the BeneficiayBankAccount builds the association with BankAccount, you're just telling rails "use that existing association, whatever it is"

SteveTurczyn
  • 36,057
  • 6
  • 41
  • 53
0

It would seem the solution was simpler.

It was necessay to add the custome foreign_key to the join table has_many itself, as in:

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

Now both directions work correctly.

Thank you for taking a look.

willyab
  • 167
  • 1
  • 10