Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7: リレーションの結果が空になる計算でクエリ送信を回避する(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

参考: 週刊Railsウォッチ20220516 矛盾するリレーション上の計算でクエリを発行しないようにする

#45030は、現時点ではmainブランチにのみ含まれており、7-0-stableブランチには含まれていません。

Rails 7: リレーションの結果が空になる計算でクエリ送信を回避する(翻訳)

従来は、countなどの計算で、矛盾するリレーションを渡してもSQLクエリが発行されていました。ここで言う"矛盾する"リレーションとは、以下のように空の配列などを渡すことを指します。

 User.where(id: []).count

このようなリレーションでデータベースを呼び出すのは無意味です。

改修前

Rails 7より前は、countsumaverageminimummaximumで使われるリレーションが矛盾していてもデータベースが呼び出されました。

  => Product.where(title: []).count
  Product Count (4.7ms)  SELECT COUNT(*) FROM "products" WHERE 1=0
  => 0
  => Product.where(title: []).sum(:price)
  Product Sum (17.5ms)  SELECT SUM("products"."price") FROM "products" WHERE 1=0
  => 0
  => Product.where(title: []).average(:price)
  Product Average (3.5ms)  SELECT AVG("products"."price") FROM "products" WHERE 1=0
  => nil
  => Product.where(title: []).minimum(:id)
  Product Minimum (5.0ms)  SELECT MIN("products"."id") FROM "products" WHERE 1=0
  => nil
  => Product.where(title: []).maximum(:id)
  Product Minimum (5.0ms)  SELECT MAX("products"."id") FROM "products" WHERE 1=0
  => nil

ご覧のとおり、矛盾するものを渡してもクエリが送信されています。

改修後

改修後は、データベースへのクエリ送信を回避するようになります。

  => Product.where(title: []).count
  => 0
  => Product.where(title: []).sum(:price)
  => 0
  => Product.where(title: []).average(:price)
  => nil
  => Product.where(title: []).minimum(:id)
  => nil
  => Product.where(title: []).maximum(:id)
  => nil

詳しくは#45030を参照してください。

関連記事

Railsエンジンは使いすぎに注意(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。