ユースケース
たとえば、年齢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