Ruby on Rails 4:挖掘结果以散列

时间:2016-03-15 12:24:14

标签: ruby ruby-on-rails-4

我该怎么转:

Person.all.pluck(:id, :name)

[{id: 1, name: 'joe'}, {id: 2, name: 'martin'}]

不必.map每个值(因为当我从.pluck中添加或删除时,我必须对.map执行相同的操作)

10 个答案:

答案 0 :(得分:24)

您可以map结果:

Person.all.pluck(:id, :name).map { |id, name| {id: id, name: name}}

如@alebian所述: 这比

更有效
Person.all.as_json(only: [:id, :name])

原因:

  • pluck仅返回已使用的列(:id,:name),而另一个解决方案返回所有列。根据表格的宽度(列数),这会产生很大差异
  • pluck解决方案不会实例化Person个对象,也不需要为模型分配属性等等。相反,它只返回一个包含一个整数和一个字符串的数组。
  • as_json再次比简单map有更多开销,因为它是将模型转换为哈希的通用实现

答案 1 :(得分:23)

你可以这么做

Person.select(:id,:name).as_json

你也可以试试这个

Person.all.as_json(only: [:id, :name])

答案 2 :(得分:10)

我看到三个选项:

1) pluckmap

Person.pluck(:id, :name).map { |p| { id: p[0], name: p[1] } }

2) pluck加上map加上zip以及一个使其成为DRY-er的变量:

attrs = %w(id name)
Person.pluck(*attrs).map { |p| attrs.zip(p).to_h }

3)或者您可能根本不使用pluck,尽管效果要差得多:

Person.all.map { |p| p.slice(:id, :name) }

答案 3 :(得分:5)

如果使用postgresql,则可以在pluck方法中使用json_build_object函数: https://www.postgresql.org/docs/9.5/functions-json.html

这样,您可以让db创建哈希。

Person.pluck("json_build_object('id', id, 'name', name)")
#=> [{id: 1, name: 'joe'}, {id: 2, name: 'martin'}]

答案 4 :(得分:3)

在使用ID作为键并且名称为值:

之后,可以使用哈希值
Person.all.pluck(:id, :name).to_h

{ 1 => 'joe', 2 => 'martin' }

不确定这是否符合您的需求,但作为选项提供。

答案 5 :(得分:3)

您可以使用名称恰当的pluck_to_hash gem: https://github.com/girishso/pluck_to_hash

它将使用pluck_to_hash方法扩展AR,其方法如下:

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

它声称比使用AR selectas_json

快几倍

答案 6 :(得分:2)

pluck_all gem与pluck_to_hash几乎完全相同。它声称它的速度提高了30%。 (参见基准here)。

<强>用法:

Person.pluck_all(:id, :name)

答案 7 :(得分:1)

最简单的方法是结合使用pluck方法和zip方法。

attrs_array = %w(id name)
Person.all.pluck(attrs_array).map { |ele| attrs_array.zip(ele).to_h }

如果在整个应用程序中都使用该方法,则也可以创建一个辅助方法。

def pluck_to_hash(object, *attrs)
  object.pluck(*attrs).map { |ele| attrs.zip(ele).to_h }
end

考虑通过将self声明为默认接收者,而不是将Person.all作为object变量来进行修改。

详细了解zip

答案 8 :(得分:0)

如果您有多个属性,可以这样做是为了保持整洁:

Item.pluck(:id, :name, :description, :cost, :images).map do |item|
  {
    id:          item[0],
    name:        item[1],
    description: item[2],
    cost:        item[3],
    images:      item[4]
  }
end

答案 9 :(得分:0)

这是一种对我有效的方法:

    def pluck_to_hash(enumerable, *field_names)
      enumerable.pluck(*field_names).map do |field_values|
        field_names.zip(field_values).each_with_object({}) do |(key, value), result_hash|
          result_hash[key] = value
        end
      end
    end