はじめに
Railsでアプリケーションを作成時に、モデルから特定のカラムをリストで抜いてきたい場面が時々あり、なにかいいメソッドはないかと探していたところ、このメソッドにたどり着いた。
ids
メソッドなどidカラムのリストを取得するメソッドを知っていたが他のカラムは一々、all
で全取得して、map
やselect
等を駆使してループ処理を行い、対象のカラムのリストを取得していたので、このメソッドを使用することでかなり簡略化につながる
pluckメソッドについて
上記でも簡単に説明したように、対象のカラムのみを指定してリストで取得する事ができる
Railsガイドでは以下のように説明されている。
pluckは、1つのモデルで使用されているテーブルからカラム (1つでも複数でも可) を取得するクエリを送信するのに使用できます。引数としてカラム名のリストを与えると、指定したカラムの値の配列を、対応するデータ型で返します。
実際の使い方について
以下のようなモデルがあると仮定して、サンプルのコードを書いていく
Userモデル
型 | カラム名 |
---|---|
id | integer |
name | string |
age | integer |
id | name | age |
---|---|---|
1 | hoge | 21 |
2 | fuga | 30 |
2 | hogehoge | 34 |
基本的な使い方
User.pluck(:name)
# SELECT name FROM users
# => ['hoge', 'fuga', 'hogehoge']
その他の使い方
引数を複数のカラムを渡すことで、指定したカラムのリストも取得できます。
戻り値が二次元配列になってかえってくるのでそこだけ注意が必要になります。
User.pluck(:name, :age)
# SELECT name, age FROM users
# => [['hoge', 21], ['fuga', 30], ['hogehoge', 34]]
pluckメソッドを使うことのメリット
コードの冗長化を防ぎ、スッキリ書ける
仮にpluck
を使わないで上記と同じような結果が得られるコードを書いてみましょう
# pluckを使わない場合
User.select(:name).map{|user|user.name}
User.select(:name, :age).map{|user|[user.name, user.age]}
発行されるSQLが変わる
mapメソッドを駆使して同じような結果は得られますが、実はRailsが発行するSQL文が変わってきます。
# mapを使用したパターン
User.all.map{|user|user.name}
=> SELECT users.* FROM users
# pluckを使用したパターン
User.pluck(:name)
=> SELECT name FROM users
上記のSQLを見比べると前者はSELECT users.* FROM users
でusers
テーブルのカラムを一旦すべて取得しているのに対して、後者は SELECT name FROM users
で users
テーブルのname
カラムのみを取得しています。
カラムすべてを取得するより、対象を指定してあげて取得する方がパフォーマンスや負荷もこ後者の方が基本的にはよくなるはずです。
ただ便利だから使うのではなく、パフォーマンス等も考慮して最適なメソッドを選べると良さそうです。
その他pluckを使う時の注意点について
Railsガイドでは以下のように記載されています
pluckは、selectなどのRelationスコープと異なり、クエリを直接トリガするので、その後ろに他のスコープをチェインすることはできません。ただし、構成済みのスコープをpluckの前に置くことはできます。
つまり、pluck
メソッドの後ろには絞り込みやソートの条件を付ける事ができないということです。
以下のような書き方はエラーとなります。
User.pluck(:name).limit(3)
User.pluck(:age).order(id: "DESC")
ただし、pluck
を使う前に予めスコープを設定しておくことで取得する事ができます。
例えば年齢カラムのリストを降順で取得したい場合は以下のように記述できます。
User.order(age: "DESC").pluck(:age)
# => [34, 30, 21]