我有一个像这样的ActiveRecord模型:
class Person < ActiveRecord::Base
attr_accessible :name
end
并且需要将Person
id
哈希映射到name
s:
{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方法有任何缺点,我可能不知道吗?谢谢!
答案 0 :(得分:3)
以下是对这种情况以及处理它的各种策略的非常好的描述: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
答案 1 :(得分:1)
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"}
请参阅:
答案 2 :(得分:0)
为避免加载所有对象,您可以这样做:
hash = Hash.new
ActiveRecord::Base.connection.execute("SELECT id, name FROM persons").each {|person| hash[person['id'].to_s] = person['name'].to_s}
答案 3 :(得分:0)
我的公司之前使用过Plucking Multiple Columns in Rails 3之一的策略。 但是我们无法从Rails 3升级到Rails 4,因为它在Rails 4中不起作用。
我建议使用pluck_all gem,它在Rails 3,4,5中具有较高的测试覆盖率,因此您不必担心将来的升级。