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

Rails 7.2: ActiveRecord::Base#pluckにハッシュ値を渡せるようになった(翻訳)

概要

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

Rails 7.2: ActiveRecord::Base#pluckにハッシュ値を渡せるようになった(翻訳)

グラフやレポートで構成されたダッシュボードを目にすることは普段からよくあります。このようなグラフやレポートを素早く作成するには、さまざまなデータベーステーブルから特定のデータを取得するクエリを高速化する必要があります。

ActiveRecord::Base#pluckメソッドは、レコード全体を読み込まずに、データベースから1個以上の属性をクエリするのに使われます。pluckの結果は属性値の配列として返されます。

User.pluck(:id, :name, :email)

上のコードから以下のクエリが生成されます。

SELECT users.id, users.name, users.email FROM "users"

上のクエリの結果から以下の配列を得られます。

#=>
  [
    [1, "David Heinemeier Hansson", "dhh@hey.com"],
    [2, "Rafael França", "rafael@franca.dev"],
    [3, "Vipul Amler", "vipul@saeloun.com"]
  ]

🔗 改修前

クエリでフィールドを取得するときは、単一のテーブルからの取得に限定されず、複数テーブルからも取得できます。

カラム名はシンボル形式で指定可能ですが、従来は単一のテーブルからカラムをフェッチするときしかシンボル指定を利用できません。
複数テーブルをJOINしたい場合は、テーブル名を指定するために以前の文字列形式を使わなければなりませんでした。

Raila 7.2より前は、以下の構文で特定のフィールドをフェッチできました。

Employee
  .joins(:companies)
  .pluck("employees.id, employees.name, companies.id, companies.name")

上のコードから以下のクエリが生成されます。

SELECT employees.id, employees.name, companies.id, companies.name
FROM "employees"
INNER JOIN "companies"
ON companies.id = employees.company_id

上のクエリの結果から以下の配列が得られます。

#=>
  [
    [1, "David Heinemeier Hansson", 1, "37signals"],
    [2, "Jason Fried", 1, "37signals"],
    [3, "Rafael França", 2, "Shopify"],
    [4, "Vipul Amler", 3, "Saeloun"]
  ]

🔗 改修後

Rails 7.2から、ActiveRecord::Base#pluckにハッシュ値を渡せるようになりました(#51565)。これにより、生SQLを使わずに同じクエリが可能になりました。

改修後の同じコードを見てみましょう。

Employee
  .joins(:companies)
  .pluck(employees: [:id, :name], companies: [:id, :name])

上のコードから以下のクエリが生成されます。

SELECT employees.id, employees.name, companies.id, companies.name
FROM "employees"
INNER JOIN "companies"
ON companies.id = employees.company_id

pluckを用いて実装されているpickメソッドにも同じことが適用されます。

pickメソッドは、relation.limit(1).pluck(*column_names).firstのショートハンドであり、リレーションが既に1行にまで絞り込まれている場合に便利です。

Employee
  .joins(:companies)
  .where(id: 1)
  .pick(employees: [:id, :name], companies: [:id, :name])

上のコードから以下のクエリが生成されます。

SELECT employees.id, employees.name, companies.id, companies.name
FROM "employees"
INNER JOIN "companies"
ON companies.id = employees.company_id
WHERE employees.id = 1
LIMIT 1

上のクエリの結果から以下の配列が得られます。

#=>
[1, "David Heinemeier Hansson", 1, "37signals"]

なお、以下の過去記事で既に取り上げたように、selectreselectにも同様にハッシュ値を渡せます。

関連記事

Rails 7.1: 自動生成されるインデックス名の長さが上限を超えないようになった(翻訳)

Rails: Active Recordメソッドのパフォーマンス改善とN+1問題の克服(翻訳)


CONTACT

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