2009-12-22 25 views
3

我已將兩個模型BusinessesRatings關聯。一個企業可以多次評級,每個評級存儲從0到5的整數。Rails使用來自相關表格的數據查找和排序

我想創建一個「名人堂」頁面,其中我列出前10位的業務,通過基於平均值排序業務評級(這將使用Ratings模型)並將結果限制爲10.

我不知道如何爲控制器編寫hall_of_fame方法,還是我還需要一個幫助器?

回答

7

假設你有一個的has_many和belongs_to的兩個模型之間的關係,你可以嘗試使用(很方便)的MySQL GROUP BY子句,這是在Rails的支持:如果你想添加

@hall_of_fame = Business.find(
           :all, 
           :joins => :ratings, 
           :group => 'business_id', 
           :order => 'AVG(ratings.rating) DESC', 
           :limit => 10 
          ) 

平均等級,你可以將其包含在:選擇參數,因爲這樣的:

@hall_of_fame = Business.find(
           :all, 
           :select => 'businesses.name, AVG(ratings.rating)' 
           :joins => :ratings, 
           :group => 'business_id', 
           :order => 'AVG(ratings.rating) DESC', 
           :limit => 10 
          ) 

當然,如果有表之間沒有衝突的列名,你可以安全地刪除龍頭「企業。」和「收視率」。來自:select和:order參數。

您可能希望在模型中使用此代碼創建一個方法,而不是在控制器中創建該方法,但這取決於您。

+0

不要爲讓你可以使用:可以選擇指定一個閾值。 – EmFi 2009-12-22 00:50:41

+0

非常感謝!正是我需要的。 – mattonrails 2009-12-26 20:56:49

0

在你的控制器,你可以抓住前10名的企業有類似的東西:

top10 = Business.average('ratings.rating', :joins => 'INNER JOIN ratings ON businesses.id = ratings.business_id', :group => 'businesses.id', :order => 'avg_ratings_rating DESC', :limit => 10) 

# example of using results of above line 
top10.each { |id, avg| puts Business.find(id).name + " score: " + avg.to_s } 

相反的:order => 'avg_ratings_rating'你可以寫:order => 'avg(ratings.rating)'。結果它會返回一個有序的散列。當你迭代它時,你會得到你想要的。

可能是一個更好的辦法是一個類的方法添加到您的商業模式是這樣的:

def self.getTop10 
    average('ratings.rating', :joins => 'INNER JOIN ratings ON businesses.id = ratings.business_id', :group => 'businesses.id', :order => 'avg_ratings_rating DESC', :limit => 10) 
end 

然後在控制器,你可以這樣做:

top10 = Business.getTop10 
相關問題