QA@IT

Rails での join した結果をオブジェクトに保存したい

10015 PV

ActiveRecord で、例えば User 1 - * Article なリレーションがあったとします。

Article のユーザーも一緒に取得したい時、

@article = Article.find(params[:id])
@user = @article.user

とすれば取れるには取れるんですが、2回SQLが走ってしまいます。これが、複数のリレーションになってくると効率悪いなぁと思ってしまいます。

ActiveRecord の join を調べてみると、joinするのはいいものの、今回でいう User は Articleオブジェクトに保存できないので、こういう場合は Rails でどう書くのがスマートか知りたいです。

よろしくお願いします。

回答

findするまえにincludesしておくとムダなクエリが減ると思います。

Article.includes(:user).find(params[:id])

でおおよそ希望通りのクエリになるかと思います。

おおよそ、と書いたのは関連の方向(belongs_toなのかhas_manyなのか、またはhas_oneなのか)によって、どのように先読みすると効率が良いか、いろいろ挙動が変わるためです。

この種の問題は、Rails界隈(に限りませんが)では、「N+1問題」とよんだり、先読みを「eager load」とよんだりしているので、より詳しく知りたい場合、このあたりの後で検索してみてください。

編集 履歴 (0)
  • eager load とは聞いたことがあるものの、こういうときに利用するものだったのですね。早速調べてみます。

    ありがとうございました!
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。