Reputation: 3456
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.
Upvotes: 34
Views: 23697
Reputation: 1403
@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)
Upvotes: 0
Reputation: 1942
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.
Upvotes: 52
Reputation: 3120
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.
Upvotes: 1
Reputation: 5204
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
Upvotes: 6
Reputation: 617
@andrewCone - It should be like this:
User.limit(:10).pluck_to_hash([:id, :name, :email, :created_at])
Upvotes: 0
Reputation: 369
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}]
#
Upvotes: 14
Reputation: 38645
Use select
instead of pluck
:
def jsontest
@users = User.select('id, name, email, created_at').limit(10)
render json: @users
end
Upvotes: 23