Rails – 给定一组用户 – 如何获得电子邮件的输出?
我有以下内容:
@users = User.all
用户有几个字段,包括电子邮件
我希望能够获得所有@users电子邮件的列表。
我试过了:
@users.email.all but that errors w undefined
想法? 谢谢
(按流行需求,发布作为真实答案)
我不喜欢fl00r的解决方案是它在数据库中为每个记录实例化一个新的User对象; 这只是不规模。 这对于一个只有10封电子邮件的表来说非常棒,但是一旦你开始涉及成千上万,你就会遇到问题,主要是Ruby的内存消耗。
通过在模型上使用connection.select_values以及一点ARel优点,可以解决这个小问题:
User.connection.select_values(User.select("email").to_sql)
这将为您提供数据库中电子邮件地址的直接字符串。 没有对用户对象User.select("email")
并且比直接的User.select("email")
查询更好地扩展,但我不会说它是“最佳规模”。 可能有更好的方法来做到这一点,我还没有意识到。
重点是: String
对象将使用比User
对象更少的内存,因此您可以拥有更多内存。 它也是一个更快的查询,并没有很长的路要走(运行查询,然后映射值)。 哦, map
也需要更长的时间。
如果您使用的是Rails 2.3 …
然后你必须手动构建SQL,我很遗憾地说。
User.connection.select_values("SELECT email FROM users")
只是提供了Rails 3提供的帮助程序的另一个示例。
User.select(:email).map(&:email)
我仍然发现connection.select_values是一个有效的方法来解决这个问题,但我最近发现了一个内置在Rails中的默认AR方法,可以为你做这个: pluck
。
在您的示例中,您需要执行的所有操作都是:
User.pluck(:email)
select_values方法在极大的数据集上可以更快,但那是因为它没有对返回的值进行类型转换。 例如,布尔值将返回它们在数据库中的存储方式(如1和0),而不是真的| 假。
pluck方法适用于ARel,因此您可以菊花链式连接:
User.order('created_at desc').limit(5).pluck(:email)
只需使用:
User.select("email")
虽然我经常访问SO,但我今天才注册。 不幸的是,这意味着我没有足够的声誉来评论其他人的答案。
回顾Ryan上面的答案,你可以扩展ActiveRecord :: Base来创建一个方法,允许你以更干净的方式在整个代码中使用它。
在config / initializers中创建一个文件(例如,config / initializers / active_record.rb):
class ActiveRecord::Base def self.selected_to_array connection.select_values(self.scoped) end end
然后,您可以在ARel声明的末尾链接此方法:
User.select('email').selected_to_array User.select('email').where('id > ?', 5).limit(4).selected_to_array
使用它来获取所有电子邮件的数组:
@users.collect { |user| user.email } # => ["test@example.com", "test2@example.com", ...]
或简写版本:
@users.collect(&:email)
您应该避免使用User.all.map(&:email)
因为它会创建大量消耗大量内存的ActiveRecord对象,其中很大一部分将不会被Ruby的垃圾收集器收集。 它也是CPU密集型的。
如果您只想从数据库中只收集一些属性而不牺牲性能,高内存使用率和CPU周期,请考虑使用Valium。
https://github.com/ernie/valium
以下是获取数据库中所有用户的所有电子邮件的示例。
User.all[:email]
或仅适用于订阅或其他任何用户。
User.where(:subscribed => true)[:email].each do |email| puts "Do something with #{email}" end
出于上述原因,使用User.all.map(&:email)
被认为是不好的做法。