如何在Rails3.x中提取多个属性?

How to pluck multiple attributes in Rails 3.x?

我有一个这样的 ActiveRecord 模型:

class Person < ActiveRecord::Base
  attr_accessible :name
end

并且需要获取哈希映射 Personid 到他们的 name

{1 => "Paul", 2 => "Aliyah", 3 => ... }

现在,显而易见的方法是

Person.all.collect { |p| [p.id, p.name] }.to_h

但是,我不需要实例化每个 Person,我只需要哈希。在 Rails 4 中,我可以 .pluck(:id, :name) 而不是 collect,但是在 3.x 中,pluck 只接受一个参数。但是我发现这个解决方法可以在不加载模型的情况下获得我想要的东西:

Person.all.group(:id).minimum(:name)

问题:我会在地狱中燃烧吗?此外,是否有更优雅的方法来执行此操作,这种 hacky 方法是否有我可能不知道的缺点?谢谢!

要避免加载所有对象,您可以这样做:

hash = Hash.new
ActiveRecord::Base.connection.execute("SELECT id, name FROM persons").each {|person| hash[person['id'].to_s] = person['name'].to_s}

下面是对这种情况的很好的描述以及处理它的各种策略:Plucking Multiple Columns in Rails 3

我更喜欢制作并包含一个模块的建议解决方案:

# multi_pluck.rb
require 'active_support/concern'

module MultiPluck
  extend ActiveSupport::Concern

  included do
    def self.pluck_all(relation, *args)
      connection.select_all(relation.select(args))
    end
  end
end
class Person < ActiveRecord::Base
  attr_accessible :name

  def self.pluck_id_and_name
     result = connection.select_all(select(:id, :name))
     if result.any?
       # if you are using Ruby 2.1+
       result.to_h
       # Works in 1.9.3+
       Hash[result]
     end
  end
end

由于结果应该是一个数组数组,我们可以使用巧妙的技巧来获得一个散列,其中第一个元素作为键,第二个元素作为值:

Hash[ [ [1, "Joe"], [2, "Jill"] ] ] 
# => { 1 => "Joe", 2 => "Jill"}

参见:

  • Convert array of 2-element arrays into a hash, where duplicate keys append additional values

我公司以前使用过Plucking Multiple Columns in Rails 3中的一种策略。 但是我们在从 Rails 3 升级到 Rails 4 时遇到了问题,因为它在 Rails 4 中不起作用。

我建议使用 pluck_all gem,它在 Rails 3、4、5 中具有很高的测试覆盖率,这样您就不会担心将来的升级。