【问题标题】:Fetch ActiveRecord query result as an array of hashes with chosen attributes获取 ActiveRecord 查询结果作为具有选定属性的哈希数组
【发布时间】:2016-11-11 02:57:24
【问题描述】:

模型User 具有firstlastlogin 作为属性。它还有一个名为name 的方法,用于连接firstlast

我想要的是遍历Users 记录并创建一个具有我想要的属性的哈希数组。像这样:

results = []
User.all.map do |user|
    record = {}
    record["login"] = user.login
    record["name"] = user.name
    results << record
end

在 Ruby 中有没有更简洁的方法来做到这一点?

【问题讨论】:

  • 您使用的是什么关系型数据库? (MySQL、Postgres)

标签: ruby-on-rails arrays ruby activerecord hash


【解决方案1】:

您可以使用ActiveRecord::QueryMethods#selectActiveRecord::Relation#as_json

User.select(:login, '(first || last) as name').as_json(except: :id)

【讨论】:

  • 这很酷,但是会创建一个大哈希,这对于创建记录毫无用处。还选择返回ActiveRecord_Relation 和 to_hash 方法引发错误。
  • @Зелёный:这有点意思,还是我错过了什么?再加上你对创造记录的假设,我猜..
  • User.select(:id, :name).map(&amp;:attributes) 这是工作代码。
  • 这段代码不应该工作。你能添加User.select(:login, :name).class的输出吗?
  • @Зелёный:我的错,我确定我在谈论 as_json 方法。
【解决方案2】:

尝试映射User.all 会导致性能问题(稍后,如果不是现在)。为避免实例化所有 User 对象,您可以使用pluck 直接从 DB 中获取数据,然后对其进行映射。

results = User.all.pluck(:login, :first, :last).map do |login, first, last|
  { 'login' => login, 'name' => first << last }
end

实例化所有用户将会有问题。甚至as_json 关系方法也能做到这一点。使用这种方法甚至可能会出现问题,具体取决于有多少用户。

此外,这假设 User#name 真的只是在做 first + last。如果不一样,你可以更改块中的逻辑。

【讨论】:

  • 是的,我实际上不使用User.all,它是特定查询的结果,我把 User.all 放在问题中只是为了简化,因为重要的是返回:用户的记录模型。你的回答也是正确的,但@spickermann 先回答了。 +1,谢谢!
  • 没问题,如果是大型查询,请确保注意性能影响:)
  • 这是一个用于自动完成目的的特定查询,在最坏的情况下它会返回几十个结果。
【解决方案3】:

我认为,名称不佳且文档记录不佳的方法ActiveRecord::Result#to_hash 可以满足您的需求。

User.select(:login, :name).to_hash

名字不好,因为它实际上返回了一个哈希数组,对于一个名为to_hash的方法来说,这看起来很糟糕。

【讨论】:

  • to_hash 用于结果集,这是执行原始查询时返回的内容,而不是关系
  • 另外,name不是属性,是返回字符串的方法。
【解决方案4】:

我会写:

results = User.all.map { |u| { login: u.login, name: u.name } }

【讨论】:

  • 谢谢!我做了users.map { |u| { "login" =&gt; u.login, "name" =&gt; u.name } } 因为我需要键是字符串而不是符号。
猜你喜欢
  • 2014-06-14
  • 2023-03-05
  • 2010-10-29
  • 2022-11-12
  • 2017-09-23
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
相关资源
最近更新 更多