如何让ActiveRecord的pluck也返回用于在json中渲染的列名?

时间:2013-12-27 03:42:24

标签: ruby-on-rails activerecord

def jsontest
   @users = User.all.limit(10)
   render json: @users
end

产量

{
...

"id": 7,
"name": "Sage Smith",
"email": "example-6@railstutorial.org",
"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

...
}

但我想省略此API中的某些字段,因此我使用pluck

def jsontest
  @users = User.all.limit(10).pluck(:id, :name, :email, :created_at) ###
  render json: @users
end

但是当我想通过散列键访问每个对象的属性时,pluck返回一个只有值的数组。

[
...

    7,
    "Sage Smith",
    "example-6@railstutorial.org",
    "2013-10-17T02:29:15.638Z"

...    

]

那么如何才能有效地获取值及其键?

我意识到我可以通过@users扫描并在拔除之前抓住密钥并重新创建哈希,但是我希望有一些方便的方法能够完全符合我的要求。

7 个答案:

答案 0 :(得分:47)

vee的答案很好,但我有一点需要注意。 select为结果中的每一行实例化User,但pluck不会。如果你只返回一些物品,这并不重要,但如果你要返回大批量(50,100等),你将会付出重大的性能损失。

我遇到了这个问题,然后我又回到了采摘:

#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(['id, name, email, created_at'])

它很丑陋,但它可以获得你想要的哈希值,而且速度很快。

我已将其更新以反映Mike Campbell在10月11日发表的评论。

答案 1 :(得分:19)

使用select代替pluck

def jsontest
  @users = User.select('id, name, email, created_at').limit(10)
  render json: @users
end

答案 2 :(得分:14)

创建一个简单的pluck_to_hash gem来实现这一目标。 https://github.com/girishso/pluck_to_hash

用法示例..

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}]
#

答案 3 :(得分:4)

使用选定列返回用户哈希值的最快方法是使用ActiveRecord::Base.connection.select_all方法。

sql = User.select('id, name, email, created_at').limit(10).to_sql
@users = ActiveRecord::Base.connection.select_all(sql)
render json: @users

答案 4 :(得分:0)

@ girishso的宝石很棒,但我的项目是在Rails 3中。它没有用。

article对我有帮助,或安装pluck_all gem来实现此目的。

用法:

constructor (props) {
  this.state = {opacity: 0.5}
}

render () {
  return (
    <TouchableHighlight 
      onPressOut={() => this.setState({opacity: 0.5})}
      opacity={this.state.opacity}
    >
      ....
    </TouchableHighlight>
  );
}

答案 5 :(得分:0)

您可以将数据和列名一起提取为:

@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 } }

这将提取数据并根据您的需要对其进行映射。与pluck相比,使用select的一个优势是可以将joins与{{1}}一起使用。

答案 6 :(得分:-1)

@andrewCone - 应该是这样的:

User.limit(:10).pluck_to_hash([:id, :name, :email, :created_at])