假设我有一个属性name
和badge_number
属性的User
对于 JavaScript 自动完成字段,我希望用户能够开始键入用户名并获得选择列表。
我正在使用提供所需JS的Materialize,我只需要以这种格式为其提供数据:
data: { "Sarah Person": 13241, "Billiam Gregory": 54665, "Stephan Stevenston": 98332 }
这不行:
User.select(:name, :badge_number) => { name: "Sarah Person", badge_number: 13241, ... }
这感觉是重复的、令人讨厌的和多余的(和重复的(:
user_list = User.select(:name, :badge_number)
hsh = {}
user_list.each do |user|
hsh[user.name] = user.badge_number
end
hsh
。虽然它确实给了我预期的结果,但随着时间的推移,性能会很糟糕。
还有什么比这个奇怪、黏糊糊的循环更好的方法吗?
这将给出所需的输出
User.pluck(:name, :badge_number).to_h
编辑
虽然上面的代码是一行,但它在内部仍然有循环。将此类循环卸载到数据库可能会提高处理过多行时的性能。但是没有与数据库无关的方法可以在活动记录中实现此目的。按照这个答案在Postgres中实现这一目标
如果你的RDBMS是Postgresql,你可以使用Postgresql函数json_build_object
来应对这种特定情况。
User.select("json_build_object(name, badge_number) as json_col")
.map(&:json_col)
整个json也可以使用Postgresql提供的函数构建。
User.select("array_to_json(array_agg(json_build_object(name, badge_number))) as json_col")
.limit(1)[0]
.json_col