Reputation: 10207
In my Invoice
model I am trying to fetch all outstanding invoices:
class Invoice < ActiveRecord::Base
has_many :payments
def self.outstanding
where("outstanding_amount != 0")
end
private
def outstanding_amount
total - payments.to_a.sum(&:amount_in_cents)
end
end
This doesn't work, however, because I don't have a database column outstanding_amount
. Is there any way to run a where
clause on a function rather than a database field?
Thanks for any help.
Upvotes: 0
Views: 98
Reputation: 78513
You need to pass the expression as part of a having clause. I'll defer to RoR wizards for the active record syntax, but your final query should amount to something like:
select ...
from ... join payments on ...
where ...
group by ...
having total != sum(payments.amount)
If most rows are imbalanced (unlikely), an alternative can be a correlated subquery:
select ...
from ...
where ...
and total != (select sum(amount) from payment where ...)
(Don't do the above if most rows are imbalanced, because performance will suck.)
A last alternative (which I'd actually recommend) is to maintain a paid
column -- ideally, though not necessarily, using triggers. You could then use:
select ...
from ...
where ...
and total != paid
Better yet, you can rephrase the latter like:
where total - paid != 0
And then add a partial index on (total - paid) where (total - paid != 0)
, for maximum performance.
Upvotes: 3