多くのデータを取り込み、計算を実行し、大きなテーブルの一部として吐き出すレポートを生成する必要があります。これを行うことは困難ではない。しかし、既存のメソッドを使用できるようにして、1000のSQLクエリを生成しないようにするのはもっと難しいです。これは、月の初めに言って口座残高を取得するために使用することができActiveRecordを使用して効率的にレポートを生成する
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
残高のテーブルをしたい場合。だから、例えば:(
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