如何为具有两个外键的模型创建范围?

How to make scope for model, that has two foreign keys?

我有模型 AccountTransaction

并且模型 AccountTransaction 中有两个外键。

transaction.rb:

  belongs_to :credit_account, class_name: 'Account',
    foreign_key: 'credit_account_id', optional: true
  belongs_to :debit_account, class_name: 'Account',
    foreign_key: 'debit_account_id', optional: true

此外,事务有列 debit_amountcredit_amount

account.rb:

  has_many :debit_account_transactions,
    class_name: 'Transaction',
    foreign_key: 'debit_account_id',
    dependent: :nullify
  has_many :credit_account_transactions,
    class_name: 'Transaction',
    foreign_key: 'credit_account_id',
    dependent: :nullify

我想设定范围,即按交易总和 (debit_amount + credit_amount) 对账户进行排序,使用范围后,我将为每个账户输出 total_amount。

现在,我有下一个范围:

joins(:credit_account_transactions, :debit_account_transactions)
      .where('transactions.created_at >= ?', 1.month.ago)
      .select(
        'accounts.*',
        'SUM(transactions.debit_amount_cents) AS total_debit_amount',
        'SUM(transactions.credit_amount_cents) AS total_credit_amount',
        'SUM(transactions.credit_amount_cents + transactions.debit_amount_cents) AS total_amount'
      )
      .order('total_amount DESC')
      .group('accounts.id')
  end

但它不能正常工作。 不算 debit_amount.

Account.accounts_balance.first.total_credit_amount
=> 1500
Account.accounts_balance.first.total_debit_amount 
=> 0

但是如果在 joins(:credit_account_transactions, :debit_account_transactions) 中交换 :credit_account_transactions:debit_account_transactions 它将计算 total_debit_amount,而 total_credit_amount - 不会。

您将加入同一个 table 两次。它们会有所不同,并且必须以不同的方式引用。 Rails 尝试变得聪明并重命名第二个连接。

运行 只需 Account.joins(:credit_account_transactions, :debit_account_transactions) 并查看它产生的 sql。它可能是这样的:

SELECT "accounts".* FROM "accounts"
INNER JOIN "transactions"
  ON "transactions"."credit_account_id" = "accounts"."id"
INNER JOIN "transactions" "credit_account_transactions_accounts"
  ON "credit_account_transactions_accounts"."debit_account_id" = "accounts"."id";

在这里你可以看到在这种情况下,第二个连接被重命名为不同的东西(credit_account_transactions_accounts),你必须这样引用它。

.select(
  'accounts.*',
  'SUM(transactions.debit_amount_cents) AS total_debit_amount',
  'SUM(credit_account_transactions_accounts.credit_amount_cents) AS total_credit_amount',