Rails:将 activerecord 关系转换为数组的正确方法?

Rails: correct way of turning activerecord relation to array?

我试图 select objects uniq by an attribute, using @videos.uniq{|p| p.author}

  time = Time.new(2014, 12)
  start_time = time.beginning_of_month
  end_time = time.end_of_month

  videos = Video.where("created_at > ? AND created_at < ?", start_time, end_time).where("likes > ?", 15)
  selected_videos = videos.uniq{|p| p.author}
  puts videos.count, videos.class, selected_videos.count 
 #=> 23, Video::ActiveRecord_Relation, 23

  videos_first = videos.first(23)
  selected_videos = videos_first.uniq{|p| p.author}
  puts videos_first.count, videos_first.class, selected_videos.count
  #=> 23, array, 10

.uniq 不适用于 ActiveRecord_Relation。问题是查询returns一个Video::ActiveRecord_Relation,但是我需要array.

当然,这可以通过使用 to_a 来实现,但是这样优雅吗?

  1. 正确的处理方式是什么?
  2. 是否可以将 .uniq 用于 activerecord:relation

如果您需要访问查询结果,只需在 ActiveRecord::Relation 实例上使用 #to_a

rails guides,您可以在 Rails 4.0 找到显着变化:“Model.all 现在 returns 一个 ActiveRecord::Relation,而不是记录数组. 如果你真的想要一个数组,请使用 Relation#to_a。在某些特定情况下,这可能会导致升级时损坏。"这对其他关系方法有效,如 :where.

selected_videos = videos.to_a.uniq{|p| p.author}

.uniq 在整个活动记录中应用时没有多大意义。

鉴于三个属性中的至少一个或多个 - idcreated_atupdated_at - 每一行都不同,应用 videos.uniq{|p| p.author} 其中 videos是一个包含所有字段的ActiveRecord::Relation,将return中的所有行ActiveRecord::Relation.

ActiveRecord::Relation 对象具有值的子集时,uniq 将能够从中找出不同的值。

例如:videos.select(:author).uniq.count 将在您的示例中给出 10。

ActiveRecord::Relation#uniqArray#uniq的区别在于Array版本接受一个块,并使用块的return值进行比较。 ActiveRecord::Relation 版本的 uniq 简单地忽略了块。

如果需要记录,可以使用ActiveRecord::Relation#load

Causes the records to be loaded from the database if they have not been loaded already. You can use this if for some reason you need to explicitly load some records before actually using them. The return value is the relation itself, not the records.

https://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-load