我们需要生成报告来提取大量数据,运行一些计算并将它们作为大表的一部分进行吐出。这样做并不困难。但是,使现有方法可以使用并且不会生成1000个SQL查询是困难的。使用ActiveRecord高效生成报告
比如我可能有一个Account
类这样的方法:
def balance_at(time=Time.now)
payments_out = self.payments.where("created_at <= ?",time).sum("amount")
payments_in = self.payments_on_account.where("created_at <= ?",time).sum("amount")
payments_in - payments_out
end
这可以用来获得一个账户余额在月初说,并在最后。它效果很好。
但是,如果我想要一个表的所有Account
余额在本月的开始和结束的事情变得愚蠢。因此,例如:
Account.includes(:payments, :payments_on_account)
将得到所有,如果我想在Ruby中的所有纯粹的紧缩这我需要的数据,但我可爱的小方法balance_at
没有做所有的Ruby运算次数(对个别情况来说会很慢)。
我可以用的东西做它在Ruby和SQL解决它取决于什么是缓存,像这样:
def balance_at(time=Time.now)
payments_out, payments_in = [payments, payments_on_account].map{|payments|
if payments.loaded?
payments.find_all{|p| p.created_at < time }.inject(0){|a,p| p.amount + a }
else
payments.where("created_at <= ?",time).sum("amount")
end
}
payments_in - payments_out
end
然而,这并不可怕可读或容易测试两种。
你会如何解决它?
我不知道是否有可能把每种类型的计算成一个范围,然后当你想用一个报告X,Y,Z在这里你只需将这些范围链接在一起。我不知道你是否会遇到某种情况,通过复杂的查询会开始互相干扰。 也许对于报告中的每一列涉及'find_by_sql'或作用域,然后您可以轻松地进行测试,并确保每列查询的价格无冲突。 – Theozaurus 2012-04-19 18:04:11