Railsアプリの最大のボトルネックとなりうるのはSQLとのやりとりである。
(Erbのレンダラーだという話は置いておく)
なので、Railsアプリでチューニングを行う時に真っ先に手をつけるのは
AR.find系のDBアクセスな部分になる。
ちょっとしたアプリを作れば、(普通にモデリングしている限り)複数の関連モデルができあがる。
この場合、チューニングのポイントはEagerLoadingにあり、
:hoge has_many :fugas
:fuga has_many :piyos
という関連にある場合は、一発ですべて取得できるこれは非常に便利。
Hoge.find(id, :include=>{:fugas=>:piyos})
とやれば、すべての関連をインスタンス化した状態で取得できる。
これは便利なので、結構めくら滅法使ってしまう。
関連先をループで回して表示したりすることがあるときは、これだけでかなりのチューニングになる。
さて、
ここからが本題。
たいていの場合、親になるモデルをインスタンス化するのはコントローラーの責務になる。
(当たり前ですが)
で、ちょっと複雑なことになったモデルクラスで、
parent.childlen.find(:all, :conditions=>[conditions])
みたいに取得するか、find_by_sqlするか、
それともループを回して配列にコピーするのがいいのか、
判断に迷うことがある。
こんな時、すでにEagerLoadingでロードされているのか、
はたまたロードされていないのか判断ができれば処理分岐で対応できる。
loaded?
これで判定がつく
parent has_many :children
だったとき、parentクラス上で、
if self.childlen.loaded?
# ループで回す処理
else
# DBアクセスを伴う処理
end
という感じ。
ちなみにテスト上では反映されないので注意。
PR