ソースコードを読んでみた~includesメソッド編~

こんにちは。デザイン・システム室の永尾です。

今年もめっきり寒くなり、お布団が恋しい時期に突入しましたね。
私は、お布団が好きです。
好きすぎて将来的にはお布団と結婚をしたいと考えています。

結婚式に招待した両親は、嫁であるお布団を見てどう思うか分かりませんが
私は我が道をいきます。

ということで、今回はincludesメソッドについての
ソースコードを読んでみた時の話を書いていきます。

includesメソッドの「よしな」

少し前に自社で運営しているサービスでN+1が発生していることに気づき
無表情でincludesメソッドを使用して解消しました。

eager_loadとpreloadをよしなに使い分けてくれるincludesメソッドを
気に入って私はよく使用していました。
便利ですよね、「よしな」

「よしな」の意味を調べてみたところ

「よしなに」で、「よろしく」「うまい具合に」といった意味に用いる表現。

好感が持てます。
知れば知るほど便利な言葉「よしな」

いや、よしな って何!
そう思ったのでメソッドのソースコードを読んで便利だけど何をしているか分からない、
そんな「よしな」の正体を知ろうと思います。
※ Rails 6.1.0 を参考にします

includesメソッド

includesメソッドの定義元を見てみたところ以下の記述がされていました。

ここで呼ばれている各メソッドの内容は以下です。

check_if_method_has_arguments!

includes!

最初に呼ばれる check_if_method_has_arguments! では
引数がなければArgumentErrorを出し、
引数があれば整地を行っています。
ちなみに整地時に使用されている compact_blak! は以下のようになっています。

そして次に呼ばれる includes! メソッドでは
includes_values に先ほど整地した値を代入しています。

つまりincludesメソッド内では、引数を整地して includes_values に代入しているのみで
よしなに関する記述はありません。

では、どこでその「よしな」の判断を行っているのかというと
eager_loading?というメソッドで行っています。

eager_loading?メソッド

クエリを発行する際に上記のメソッドが呼ばれ
その中で eager_loading? が呼ばれています。

eager_loading? が
true ・・・eager_load
false ・・・preload
のように実行されます。

eager_loading? の実装は以下です。

先ほど登場していた includes_values がここで使用されています。
他も同じように
eager_load_values にはeager_load をすると値が入り
joined_includes_values には includesしていて、かつjoinをしていると値が入り
references_eager_loaded_tables? はjoin元で references を行っていると trueを返します。

つまり、eager_loadを行う条件は
eager_loadメソッドを使用しているか
includesしていて、かつjoinかreferencesを行っている場合になります。

これが「よしな」の正体でした。

便利な「よしな」だけど

includesメソッドはいつも「よしな」に判断してくれる万能なメソッドですが
万能が故に100点の結果は出せません。

場合によっては、スロークエリを発行してしまったり
preloadの方が適切な場面でeager_loadを実行したりもします。
また一目見ただけでは、ここで使われているincludesが
eager_loadを実行しているのか、preloadを実行しているのか
分からないというデメリットもあります。

今回、コードを追うことで普段なんとなく使用していた「よしな」の正体を
理解すると同時に、他人が書いたコード読むことで多くの学びがあることにも
気づくことができた、とてもいい経験でした。

メンバー募集中 !

ファンデリー デザイン・システム室では現在メンバーを募集しています。
興味を持たれた方は、是非下記のフォームよりご応募ください。

お待ちしております!