Rails 3 – 如何通过对属性进行数学运算来对AR查询结果进行排序?

我正在构建一个控制器/视图,提供广泛的玩家排名选择(例如“十大领导者委员会”。)使用此模型:

class Player < ActiveRecord::Base attr_accessible :name, :games_played, :games_lost, :games_won, games_exited, :total_kills, :total_deaths, :total_points, :total_coins end 

在我的控制器中,我有一些明显的查询结果传递给我的视图来填充玩家排名列表:

 @top_winners = Player.order("games_won DESC").limit(10) @top_assassins = Player.order("total_kills DESC").limit(10) 

我现在需要添加一些计算排序的排序。 例子:

 @most_greedy would be sorted on: :total_coins / :games_played @most_lethal would be sorted on: :total_kills / :games_played @most_vanquished would be sorted on: :total_deaths / (:games_lost + :games_exited) 

我的方法是让所有玩家都在一个数组中,然后使用Ruby的array.sort {| a,b | block } → new_array array.sort {| a,b | block } → new_array array.sort {| a,b | block } → new_array选项。 在@most_greedy的情况下,我尝试了这个:

 rich_players = Player.order("total_coins DESC").limit(30) # only consider top 30 richest @most_greedy = rich_players.sort {|total_coins, games_played| x / y }.slice(0, 9) 

这会产生错误:

 undefined local variable or method `x' for # 

不幸的是,我微弱的AR理解和Ruby技能让我失望。 我该如何使这种方法有效? 对这类问题有不同的解决方法吗? 我在AR查询指南中没有看到这样的内容。

sort不是活动记录,它是普通的旧ruby,并使用带有两个参数的块来比较两个对象,这些对象将成为Player对象。

 @most_greedy = rich_players.sort {|x, y| (x.total_coins / x.games_played) <=> (y.total_coins / y.games_played) }.slice(0, 9) 

甚至更好,使用sort_by :

 @most_greedy = rich_players.sort_by {|x| x.total_coins / x.games_played }.slice(0, 9) 

如果你想使用数据库进行计算(这可能会产生不同的结果,也就是说,可能会找到一个不那么好的玩家,其分数比限制为10个顶级富有玩家更好),你可以试试这个…(未经测试)

 @most_greedy = Player.select('*, total_coins/games_played as greediness').order('greediness DESC').limit(10)