自動的にEager Loadingしてくれるようになる「Goldiloader」というGemが良い感じ

RailsでのDBへのクエリの組み立ては常にN+1問題との戦いですよね。N+1が発生すると大幅にパフォーマンスがダウンしてしまうので、適切な事前ロードをいかに行えるかがプログラマの腕の見せどころになります。

でもそれって本質でしょうか? DBにクエリを投げる部分の実装の詳細なのでは?

クエリが空気読めばいいじゃん!という「Goldiloader」

「それって実装の本質じゃないよね。詳細だよね。それはクエリを投げる部分(ActiveRecord)が空気読めばいいんじゃね?」

そんな思想で現れたGemがGoldiloaderです。Gemfileに加えるだけで勝手にEager Loadingしてくれるようになります。

このGemをbundleせずに以下のコードを叩くと、eachでpostsが呼ばれるたびにロードを繰り返してしまうのですが・・・

> blogs = Blogs.limit(5).to_a
# SELECT * FROM blogs LIMIT 5

> blogs.each { |blog| blog.posts.to_a }
# SELECT * FROM posts WHERE blog_id = 1
# SELECT * FROM posts WHERE blog_id = 2
# SELECT * FROM posts WHERE blog_id = 3
# SELECT * FROM posts WHERE blog_id = 4
# SELECT * FROM posts WHERE blog_id = 5

このGemをbundleした後なら、空気を読んで事前にロードしておくてくれます。

> blogs = Blogs.limit(5).to_a
# SELECT * FROM blogs LIMIT 5

> blogs.each { |blog| blog.posts.to_a }
# SELECT * FROM posts WHERE blog_id IN (1,2,3,4,5)

詳しい話はGem作成元のAUTOMATIC EAGER LOADING IN RAILSという記事をご覧ください。ここのエンジニアブログのRuby on Railsタグの記事、結構面白いです。

Goldiloader