[英]Filter records by virtual attribute rather than database field?
我在我的User
模型中使用此功能来填充表单中的选择框:
def outstanding_invoices
invoices.to_a.select { |invoice| invoice.balance < 0 }
end
问题是, balance
不是数据库字段,而是计算某些东西的方法。
因此,生成选择框需要大量的SQL查询,因为上面的函数会迭代user
拥有的每个invoice
。
是否有更快的方法来生成选择框,理想情况下只使用一个SQL查询?
一个简单的替代方案可能是将每张invoice
的balance
存储在数据库中,但我不知道这样做是因为我想将数据库保持在最低限度。
谢谢你的帮助。
根据使用计算货币值的经验,在很多情况下,将计算值与用于计算该值的参数一起存储是有意义的 - 这样您就可以针对计算值运行查询,但您还可以追溯到如何计算价值。
在您的发票示例中,我建议您在Payment
模式中实施after_save
回调。 例如:
class Payment < ActiveRecord::Base
belongs_to :invoice
def after_save
invoice.update_balance
end
end
class Invoice
has_many :payments
def self.with_open_balance
where("current_balance > 0")
end
def update_balance
update_attributes(:current_balance => balance)
end
def balance
invoiced_amount - payments.sum(:amount)
end
end
通过这种方法,您现在可以调用customer.invoices.with_open_balance
来获取该customer.invoices.with_open_balance
所有未结发票。 每当保存付款时,付款所属的发票将重新计算其余额并将该计算值存储在同一数据库事务中,从而确保一致性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.