ユースケース
たとえば、年齢20歳以上絞り込んだユーザー1人のidを取得したいとき
よくある書き方
以下のように書くことでidが取得できますが、この書き方だとパフォーマンスが悪くなる事もあります。
User.where("age > 20").pluck(:id).first
この処理を行った場合、以下の処理が実行されます。
-
whereでレコードを絞り込み -
users.idのリストをアプリケーションに返す -
users.idのリストからArrayを生成 - 生成した
Arrayに対しrubyのArray#firstで1件抽出する
この場合、アプリケーションで1件しかデータを使用しないのにDBは該当する全てのデータを返すので余計な処理やリソース消費が発生します。
対応
limit句を使用してあげます。
limit句を指定する事でDBはレコードを1件見つけた時点で検索を止めて結果を返すので高速になります。(全ての場合に高速になる訳ではありません。)
- User.where("age > 20").pluck(:id)).first
+ User.where("age > 20").limit(1).pluck(:id)).first
rails6から追加されるActiveRecord::Relation#pick
上の.limit(1).pluck(:id)).firstのショートハンドがrails6のpickメソッドです。
このメソッドを使用する事でさらに簡潔にコードを記述する事ができます。
- User.where("age > 20").limit(1).pluck(:id)).first
+ User.where("age > 20").pick(:id)
実装を確認する
そのまんま
activerecord/lib/active_record/relation/calculations.rb
def pick(*column_names)
limit(1).pluck(*column_names).first
end