4

我有两个模型:SchoolReview.

School模型如下所示:{ID, name, city, state}

Review模型如下所示:{ID, content, score, school_id}

如何根据审查模型的分数列出前十名的学校?

我想也许是学校模型中的一种方法,如下所示:

class School < ActiveRecord::Base
 def top_schools
   @top_schools = School.limit(10)
   ...
 end
end

然后将它们循环到一个<li>列表中:

<div>
 <ul>
   <% @top_schools.each do |school| %>
      <li>school.name</li>
   <%end>
 </ul>
</div>

但是,我真的不知道如何完成该top_schools方法。

4

4 回答 4

5

你应该对每所学校进行平均评价。

如果您使用 MySQL 运行,SQL 查询应该类似于:

SELECT schools.* FROM schools 
JOIN reviews ON reviews.school_id=schools.id 
GROUP BY schools.id
ORDER BY AVG(reviews.score) DESC
LIMIT 10

在 Rails 中翻译:

在您的学校模型中:

scope :by_score, :joins => :reviews, :group => "schools.id", :order => "AVG(reviews.score) DESC"

在您的控制器中:

@top_schools = School.by_score.limit(10)

选择不包括范围限制,可以更灵活,允许显示 5 或 15。

我只测试了 MySQL 请求。我不确定我的 Rails 翻译。

于 2013-02-08T00:02:02.953 回答
0

编辑:我完全错过了该答案中的评论模型。

School.all(:select => "schools.*, AVG(reviews.score) as avg_score", 
:joins => :reviews, 
:group => 'schools.id', 
:order => 'avg_score desc', 
:limit => 10)

但是,当您添加评论时,这会变慢。我喜欢 total_score 的答案。

于 2013-02-07T23:19:54.277 回答
0

假设每所学校只有一条评论 (has_onebelongs_to),您需要先订购评论,然后找到相应的学校:

Review.order('score DESC').first(10).each do |r|
   School.find_by_id(r.school_id)
end
于 2013-02-07T23:28:50.093 回答
0

我会total_score在学校表中添加一个新字段 - 默认设置为 0。然后在 Review 模型中添加一个回调,以在向该学校添加/更新新评论时计算该学校的总分。

然后这样做: School.order("total_score DESC").limit(10)

于 2013-02-07T23:53:08.140 回答