我试图使用@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
。问题是查询返回Video::ActiveRecord_Relation
,但我需要array
。
当然,这可以通过使用to_a
来实现,但这是优雅的吗?
.uniq
使用activerecord:relation
?答案 0 :(得分:36)
如果您需要访问查询结果,只需在ActiveRecord :: Relation实例上使用#to_a
。
在rails guides,你可以在Rails 4.0上找到值得注意的变化:“Model.all现在返回一个ActiveRecord :: Relation,而不是一个记录数组。如果你真的想要一个数组,请使用Relation#to_a。在某些特定情况下,升级时可能会导致破损。“这适用于其他关系方法,例如:where。
selected_videos = videos.to_a.uniq{|p| p.author}
答案 1 :(得分:3)
.uniq
时没有多大意义。
鉴于三个属性中的至少一个或多个 - id
,created_at
和updated_at
- 对于每一行都不同,将videos.uniq{|p| p.author}
应用于{{1 }}是包含所有字段的videos
,将返回ActiveRecord::Relation
中的所有行。
当ActiveRecord::Relation
对象具有值的子集时,ActiveRecord::Relation
将能够从中找出不同的值。
例如:uniq
将在您的示例中给出10。
videos.select(:author).uniq.count
和ActiveRecord::Relation#uniq
之间的区别在于Array版本接受一个块并使用块的返回值进行比较。 uniq的ActiveRecord :: Relation版本只是忽略了块。
答案 2 :(得分:2)
如果需要记录,可以使用ActiveRecord :: Relation#load
如果尚未从数据库中加载记录,则导致这些记录。如果出于某种原因需要在实际使用之前明确加载某些记录,则可以使用此方法。返回值是关系本身,而不是记录。
https://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-load