2010-07-09 101 views
2

假設Song s have_many Comment s;我怎樣才能:按has_many關聯的屬性排序

  1. 拉從數據庫中的所有歌曲列表,按他們每個人的評論數量排序? (也就是說,首先評論最多的歌曲,評論最少的歌曲最後?)
  2. 相同,但按評論創建時間排序? (也就是說,最近創建的評論第一首歌曲,最近創建評論的歌曲最後?)

回答

1

如果您需要按照它們的評論數量進行排序 - 雖然可以直接使用SQL - 我強烈建議你使用counter_cache - 參見:http://railscasts.com/episodes/23-counter-cache-column

Ofter的是,僅僅通過find選項設置的順序如下所示:

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

這是在不同的Rails 3所以這取決於w ^你正在使用的帽子。

我也建議在Song模型上緩存最新評論創建的東西,讓您的生活更輕鬆。

你會用after_save回調的Comment模型像這樣:

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

+0

我可以在回調中忽略'self',對吧? – 2010-07-10 01:56:27

+0

是的,你可以,如果你想。它只會爬上範圍,並達到它想要的。因爲我喜歡明確,所以我傾向於不離開,但這真的取決於你。 – 2010-07-10 02:10:42

6

1)有幾個方法可以做到這一點,最簡單的是反緩存,你這樣做我創建一個列來保持計數和軌道將保持計數的速度。在這種情況下,列將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") 

與第二方法的一些注意事項,任何你想要的,你需要的歌曲選擇通過聲明包含在組中。如果你只需要拉歌與評論,然後您可以:

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" 

我希望這有助於!

+0

偉大的解釋。 +1 – 2010-07-09 05:20:10

+0

謝謝;會有'Song.all(:joins =>:comments,:order =>「comment.created_at」'也適用於(2)? – 2010-07-10 00:22:10

+0

連接只會給你帶有評論的歌曲,include會給你帶有和沒有評論的歌曲。 – 2010-07-10 00:29:33