読者です 読者をやめる 読者になる 読者になる

おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

find_by_sql したレコードで preload する方法

rails

どうしても AR の query methods だけでは要求を満たせない場合の最後の手段として、find_by_sql メソッドがあります。皆さんよく使ってると思うのですが、戻り値のレコードからさらに association をロードしようとすると N+1 になるケースがあります。かといって

User.preload(:comments).find_by_sql(sql)

のようにしても期待通りには動きません。単純に preload 部分が無視されるだけです。

ではどのように書いたらよいでしょうか。

次のように書くと期待通りに動きます(Rails 4.2.1 で試しています)。

records = User.find_by_sql(sql)
ActiveRecord::Associations::Preloader.new.preload(
  records, :comments
)
records # comments が preload されている

:comments の部分は、通常の preload と同じように、配列やハッシュを指定できます。

これで N+1 の心配をせずに済みそうです。

参考

preload associations with find_by_sql · Prathamesh Sonpatki