按has_many关联的属性排序

时间:2010-07-09 03:33:30

标签: ruby-on-rails

假设Song s has_many Comment s;我怎么能:

  1. 从数据库中提取所有歌曲的列表,并按每个歌曲的评论数量排序? (即,首先评论最多的歌曲,评论最少的歌曲最后?)
  2. 相同,但按评论创建时间排序? (即,最近创建的评论首先出现的歌曲,最近创建的评论最少的歌曲?)

2 个答案:

答案 0 :(得分:6)

1)有几种方法可以做到这一点,最简单的是计数器缓存,你这样做我创建一个列来维持计数和rails会使计数加快速度。在这种情况下,列将是comments_count

songs = Song.all(:order => "comments_count DESC")

或者你可以做一个时髦的查询:

songs = Song.all(:joins => "LEFT JOIN comments ON songs.id = comments.song_id",
                 :select => "song.name, count(*)",
                 :group => "song.name",
                 :order => "count(*) DESC")

使用第二种方法的一些注意事项,您需要在歌曲中选择的任何内容,您需要在group by语句中包含这些内容。如果您只需要带有评论的歌曲,那么您可以:

songs = Song.all(:joins => :comments, 
                 :select => "song.name, count(*)",
                 :group => "song.name",
                 :order => "count(*) DESC")

哪个看起来更好但是因为它有一个内连接你不会得到没有评论的歌曲

2)只是一个包含/加入

songs = Song.all(:include => :comments, :order => "comment.created_at"

我希望这有帮助!

答案 1 :(得分:1)

如果您需要按照他们的评论数量排序 - 虽然您可以直接使用SQL进行排序 - 我强烈建议您使用counter_cache - 请参阅:http://railscasts.com/episodes/23-counter-cache-column

之后,只需按find选项设置顺序,如下所示:

Song.all(:order => "comments_count DESC");

这在Rails 3中有所不同,因此它取决于您使用的内容。

我还建议在Song模型上缓存最新评论创建的内容,以使您的生活更轻松。

您可以使用after_save模型上的Comment回调执行此操作,例如:

self.song.update_attributes!({:last_comment_added_at => Time.now.to_s(:db)})