'How can I have ActiveRecord's pluck also return the column name for rendering in json?
def jsontest
@users = User.all.limit(10)
render json: @users
end
yields
{
...
"id": 7,
"name": "Sage Smith",
"email": "[email protected]",
"created_at": "2013-10-17T02:29:15.638Z",
"updated_at": "2013-10-17T02:29:15.638Z",
"password_digest": "$2a$10$taHk3udtWN61Il5I18akj.E90AB1TmdL1BkQBKPk/4eZ7YyizGOli",
"remember_token": "118f807d0773873fb5e4cd3b5d98048aef4f6f59",
"admin": false
...
}
But I would like to omit certain certain fields from this API, so I use pluck
def jsontest
@users = User.all.limit(10).pluck(:id, :name, :email, :created_at) ###
render json: @users
end
but pluck returns an array of only values, when I would like to have each object's attributes accessible by hash key.
[
...
7,
"Sage Smith",
"[email protected]",
"2013-10-17T02:29:15.638Z"
...
]
So how can I effectively pluck the values and their keys?
I realize I could sweep through @users and grab the keys before plucking and recreate the hash, but I'm expecting there to be some convenience method that does exactly what I want.
Solution 1:[1]
vee's answer is good, but I have one caveat. select instantiates a User for every row in the result, but pluck does not. That doesn't matter if you are only returning a few objects, but if you are returning large batches (50, 100, etc) you'll pay a significant performance penalty.
I ran into this problem, and I switched back to pluck:
#in user.rb
def self.pluck_to_hash(*keys)
pluck(*keys).map{|pa| Hash[keys.zip(pa)]}
end
#in elsewhere.rb
User.limit(:10).pluck_to_hash(*%i[id name email created_at])
It's ugly, but it gets the hash you want, and fast.
I've updated it to reflect Mike Campbell's comment on Oct 11.
Solution 2:[2]
Created a simple pluck_to_hash gem to achieve this.
https://github.com/girishso/pluck_to_hash
Usage example..
Post.limit(2).pluck_to_hash([:id, :title])
#
# [{:id=>213, :title=>"foo"}, {:id=>214, :title=>"bar"}]
#
Post.limit(2).pluck_to_hash(:id)
#
# [{:id=>213}, {:id=>214}]
#
# Or use the shorter alias pluck_h
Post.limit(2).pluck_h(:id)
#
# [{:id=>213}, {:id=>214}]
#
Solution 3:[3]
Fastest way to return hash of users with selected columns is use ActiveRecord::Base.connection.select_all method.
sql = User.select('id, name, email, created_at').limit(10).to_sql
@users = ActiveRecord::Base.connection.select_all(sql)
render json: @users
Solution 4:[4]
@andrewCone - It should be like this:
User.limit(:10).pluck_to_hash([:id, :name, :email, :created_at])
Solution 5:[5]
You can pull the data along with the column name as:
@users = User.all.limit(10)
.pluck(:id, :name, :email, :created_at)
.map {|id, name, email, created_at| { id: id, name: name,
email: email,
created_at: created_at } }
This will pull the data and map it according to how you want it. One advantage of using pluck over select is that you can use joins along with it.
Solution 6:[6]
@girishso's gem is great, but my project is in Rails 3. It doesn't work.
This article is helpful to me, or install pluck_all gem to achieve this.
Usage:
User.limit(10).pluck_all(:id, :name, :email, :created_at)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | kuboon |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | Zvi |
| Solution 5 | anonn023432 |
| Solution 6 |
