ActiveRecord関連付けのpreload/eager-loadをテストする2つの方法(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社エンジニアの「?」を「!」に。原著者の許諾を得て翻訳・公開いたします。RailsやReact.jsの開発・教育・書籍を手がけています。ActiveRecord関連付けのpreload/eager-loadをテストする2つの方法(翻訳)パフォーマンスに気を配っている開発者なら、#includes、#preload、#eager_loadなどの読み込みメソッドでN+1クエリを回避する方法をご存知でしょう。自分の仕事が正しかったかどうか、期待する関連付けが本当にpreloadされているかどうかをチェックする方法はあるのでしょうか。そもそもどうやってテストすればよいのでしょうか。Railsアプリに次の2つのクラスがあるとします。line(order_lines)を持つことができます。:orderendここでOrder.last_tenというメソッドを実装しました。これはeager-loadingする関連付けを1つ使って、最新のorderを10件返します。このコードを呼び出した後でちゃんとpreloadされるかどうかを確認してみましょう。endendpreload(:order_lines)を行ったので、order_linesが読み込まれているのかどうかを知りたいと思います。orders[0]などのOrderオブジェクトを1つ取得する必要があることをチェックするには、オブジェクトの照合を行います。ordersコレクションをチェックしても関連付けが読み込まれているかどうかはわからないため、コレクションのチェックは不要です。RSpecでのテストは以下のような感じになります。ActiveSupport::NotificationsでクエリをカウントするActiveRecordライブラリにはassert_queriesという便利なヘルパーメソッドがあり、ActiveRecord::TestCaseに含まれているのですが、惜しいことに、ActiveRecord::TestCaseはActiveRecordに含まれていません。これはRailsの内部テストで振舞いをチェックする目的にのみ利用できます。今回の目的に合わせてassert_queriesをエミュレートするのは意外に簡単です。いくつかのActiveRecordオブジェクトのグラフを操作するが、オブジェクトを返さずに計算値だけを返すという状況を考えてみましょう。このときにN+1問題が発生していないことをどうやって確認すればよいでしょうか。副作用は見当たらず、loaded?かどうかをチェックできるレコードも返されません。何か方法はないものでしょうか。endend上の状況で、Order.average_line_gross_price_todayがN+1クエリ問題を抱えていないかどうかをどのように確認すればよいでしょうか。order_lines?を読み取るときにorder.order_lines.map(&:gross_price)がSQLクエリをトリガしないことをどのように確認すればよいでしょうか(実はN+1問題が起きています)。ActiveSupport::Notificationsを使えば、SQL文が実行されるたびに通知を受け取ることができます。loadingの問題を検出するのに十分な数のレコードを作成しておいてください。loadingが発生するかどうかにかかわらずクエリの数が同じになってしまうので不十分です。今回はorderのlineが2の場合にのみ、preloadingでのクエリ数(2件、1つはすべてのorder、もう1つはすべてのline)とpreloadingされない場合のクエリ数(3件、1つはすべてのorder、残りは個別のline)に違いが生じることがわかります。:)この方法はもちろん有効ですが、責務を2つの小さなメソッドに分割できたらなおよいでしょう。責務の1つはデータベースから正しいレコードを抽出すること(IOが発生する)、もう1つはデータを変換して計算することです(IOも副作用もなし)。gemをチェックしてみてください。知りたい方に本記事を気に入っていただけた方は、日々のRailsプログラミングに役立つ知識をいつも最初に知ることができる弊社のニュースレターをぜひご購読ください。コンテンツはRuby、Rails、Web開発、リファクタリングが中心ですが、その他の話題も扱っています。Rails』もぜひチェックしてみてください。コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。enno.jpを運営。実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。Storageを使ってはいけない(翻訳)#Tags#会社紹介#自社サービス#勉強会#Rails#PHP#デザイン#実績#週刊RailsウオッチCONTACTお気軽にご相談ください。(翻訳)CONTACTTechRachoでは、パートナーシップをご検討いただける方からのご連絡をお待ちしております。お気軽にご意見・ご相談ください。