この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
サービスの開発でよく使用するデータベース(DB)。DBテーブルの特定のデータを一度に取得する方法として、mapメソッドとpluckメソッドが存在する。どちらともデータを取得するという点では同じですが、いくつか異なる点が存在します。この記事ではこれらの違いとデータを取得する際の使い分けについて説明をします。
mapメソッド
mapはrubyで使用することができるメソッドです。レシーバの要素の数だけブロックを実行し、ブロック内の結果を配列に格納して配列で返す機能があります。また、&(アンパサンド)を使用することでコードを簡略化することが可能。&には、ブロックを展開する意味がある。
["a", "b", "c"].map { |str| str.upcase } # => ["A", "B", "C"]
["a", "b", "c"].map(&:upcase) # => ["A", "B", "C"]
mapメソッドは、配列だけでなくハッシュに対しても実行することができます。mapメソッドのレシーバがハッシュでも配列を返します。
{1 => "taro", 2 => "jiro"}.map { |key, value| key.upcase } # => ["TARO", "JIRO"]
最後にmapメソッドを使用したDBデータ取得についてです。以下のユーザモデルが存在した場合、データの中から取得したいカラムを以下のように指定することで、そのカラムのデータを全て取得することができる。
#<ActiveRecord::Relation [
#<User id: 1, name: "taro", created_at: "2017-06-01 01:00:00", updated_at: "2017-06-01 01:00:00">,
#<User id: 2, name: "jiro", created_at: "2017-06-01 01:00:00", updated_at: "2017-06-01 01:00:00">
]>
User.all.map{ |user| user.id } # => [1, 2]
User.all.map{ |user| user.name } # => ["taro", "jiro"]
User.all.map(&:id) # => [1, 2]
pluckメソッド
pluckメソッドは、引数に指定したカラムの配列を返すメソッドです。このメソッドはRailsで使用できるメソッドなので、Rubyのみでは使用することができません。また、pluckメソッドには、引数に&が必要無く、複数のカラムを指定することもできます。複数のカラムを指定した時は、2次元配列で返ります。
#<ActiveRecord::Relation [
#<User id: 1, name: "taro", created_at: "2017-06-01 01:00:00", updated_at: "2017-06-01 01:00:00">,
#<User id: 2, name: "jiro", created_at: "2017-06-01 01:00:00", updated_at: "2017-06-01 01:00:00">
]>
User.pluck(:id) # => [1, 2]
User.pluck(:id, :name) # => [[1, "taro"], [2, "jiro"]]
mapとpluckの違い
mapメソッドとpluckメソッドの使い分けについて気になったので調べてみました。pluckメソッドは、mapメソッドよりも処理速度が速いと言われていますが、必ずそうとも言えないようです。pluckメソッドは、実行するたびにSQLを発行するので、データ数によっては、mapメソッドより遅くなる場合があります。mapとpluckの使い分けについてですが、参考記事によるとDBからデータを直接取得する場合はpluckメソッドを使用し、インスタンスからデータを取得する場合はmapメソッドを使用するとSQLの回数を抑えることができます。
User.pluck(:id)
user = User.where(“age > 20”)
user.map(&:name)
まとめ
簡単にmap・pluckメソッドの説明を行いました。私は、データの取得にmapメソッドしか使用せずにパフォーマンスのことも考えてきませんでした。今回の記事で少しでも多くの方がパフォーマンスに気をつけることができるようになれば幸いです。
参考記事
http://qiita.com/metheglin/items/18064851a8f00dab67f8
http://yachibit.hateblo.jp/entry/2014/03/05/002844