大量のデータを取り込み、いくつかの計算を実行し、それらを大きなテーブルの一部として吐き出すレポートを生成する必要があります。これを行うことは難しくありません。ただし、既存のメソッドを使用できるようにし、何千もの SQL クエリを生成しないようにすることは、はるかに困難です。
たとえば、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 で計算したい場合に必要なすべてのデータを取得しますが、Ruby でbalance_at
すべての数値計算を実行するのは私の素敵な小さなメソッドではありません (個々のケースでは遅くなります)。
キャッシュされているものに応じて、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
ただし、それはひどく読みやすく、テストも簡単ではありません。
どのように解決しますか?