从ActiveRecord模型或Enumerables中提取单个值的方法

88 阅读1分钟

Rails有一个伟大的、富有表现力的术语,叫做pluck ,它允许你从记录中抓取数据的一个子集。你可以在ActiveRecord模型上使用这个方法来返回一个(或几个)列。

但你也可以在普通的旧Enumerables 上使用同样的方法,以拉出响应给定键的所有值。

使用方法

在Rails中,使用pluck 来查询一个列的子集:

Shoe.all.map(&:name)
# SELECT "shoes.*" from "shoes"
# => ["Air Force 1", "NMD_2", "Air Jordans", ... ]
# This returns an array with all shoe names, but our database query pulled down all of the columns on the `shoes` table

Shoe.pluck(:name)
# SELECT "shoes.name" from "shoes"
# => ["Air Force 1", "NMD_2", "Air Jordans", ... ]
# Same result, but we only query exactly the columns we wanted

Shoe.pluck(:name, :brand)
# SELECT "shoes"."name", "shoes"."brand" FROM "shoes"
# => [["Air Jordan 1 Mid", "Nike"], ["Air Jordan 1 Mid", "Nike"], ... ]

Shoe.distinct.pluck(:brand)
# SELECT DISTINCT "shoes"."brand" FROM "shoes"
# => ["Nike", "Adidas", ... ]

当使用ActiveSupport 时,你也可以将pluckEnumerables 一起使用:

[  { id: 1, name: "David" },  { id: 2, name: "Rafael" },  { id: 3, name: "Aaron" }].pluck(:name)

# => [ "David", "Rafael", "Aaron" ]

我发现在处理来自外部API的JSON数据时,Enumerable 版本特别方便:

require "httparty"
require "active_support"
require "active_support/core_ext"

response = HTTParty.get('http://api.stackexchange.com/2.2/questions?site=stackoverflow')
questions = JSON.parse(response.body)["items"]
questions.pluck("title")

# => [
#   "JavaScript to Python - Interpreting JavasScript .filter() to a Python user",
#   "Nuxt generate and firebase gives timer warning",
#   "Variable expected error when I increment the value of a map",
#   ...
# ]

虽然pluck 最常被用于哈希值,但你可以将其用于任何响应你传入的消息的对象--包括普通的Ruby对象或Structs。

下次你发现自己调用map 来获取一个单一的值时,看看你的代码是否可以通过切换到pluck 来改进。