Rails находит и сортирует, используя данные из связанной таблицы - PullRequest
3 голосов
/ 22 декабря 2009

Я связал две модели Businesses и Ratings. Бизнес может оцениваться много раз, и в каждом рейтинге хранится целое число от 0 до 5.

Я хотел бы создать страницу «Зала славы», где я перечислю 10 лучших компаний, отсортировав их по средним рейтингам (в которых будет использоваться модель Ratings) и ограничив результаты до 10.

Я не уверен, как написать метод hall_of_fame для контроллера, или мне также понадобится помощник для этого?

Ответы [ 2 ]

7 голосов
/ 22 декабря 2009

Предполагая, что у вас есть отношения has_many и own_to между двумя моделями, вы можете попробовать использовать (очень удобный) раздел MySQL GROUP BY, который поддерживается в Rails:

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

Если вы хотите добавить среднюю оценку, вы можете включить ее в параметр: select следующим образом:

@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 голосов
/ 22 декабря 2009

В вашем контроллере вы можете получить 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...