为什么我不能在模型中使用sort_by?

时间:2010-07-19 23:32:04

标签: ruby-on-rails

我有用户模型和出价模型。我希望用户基于作为方法存储的分数来知道他们的等级是什么,即基于user.score方法的“3/7”。目前,我正在尝试将此geek_rank方法隐藏到Bid模型中:

def user_rank(my_id)
  #Finds all bids associated with parent ticket object
  bids = Bid.find_by_ticket_id(self.ticket.id)
  bids = bids.sort_by { |b| b.user.score}
  i = 0
  for b in bids
    i += 1
    if b.user_id.to_i == my_id.to_i
      myrank = i
    end
  end
  user_rank = myrank.to_s + "/" + i.to_s
end

由于某种原因,sort_by方法在控制器中工作,但在我尝试在模型中进行排序时却没有。谁能告诉我问题是什么以及我的代码如何糟糕? :)

要澄清:

我得到的实际错误是缺少错误的方法。

2 个答案:

答案 0 :(得分:4)

方法find_by_ticket_id不返回数组;它返回一个出价。 请改用find_all_by_ticket_id

bids = Bid.find_all_by_ticket_id(self.ticket.id)
bids = bids.sort_by { |b| b.user.score}

我会按如下方式重写你的方法:

def user_rank(my_id)
  # find the bid by the given id
  score = Bid.find_by_id(my_id).user.score

  # find the total number of bids for the ticket
  count  = Bid.count(:conditions => {:ticket_id => self.ticket.id})

  # find the rank
  rank   = Bid.count(:conditions => ["ticket_id =? AND users.score > ? ",
              self.ticket.id, score], :joins => :user) + 1
  "#{rank}/#{count}"
end

在这种方法中,大部分计算都是由DB完成的。

警告1

此方法将为具有相同分数的人返回相同的等级。

E.g:

#name #score   #rank
foo        5        4
bar        6        2
kate       6        2
kevin      8        1

警告2

此解决方案的性能优于您的解决方案。但它仍然需要n * 3往返服务器来计算排名。可以进一步优化解决方案,以计算一个SQL中所有用户的排名。

关于排名计算优化的文章:

Article 1

答案 1 :(得分:0)

那么,从方法返回的分数是有理数,例如3/7还是Fixnums?

如果它们是有理数,那么它们应该能够通过可用的sort_by方法进行比较:

ruby-1.8.7-p299 > require 'mathn'
 => true 
ruby-1.8.7-p299 > Rational
 => Rational 
ruby-1.8.7-p299 > Rational(3/7)
 => 3/7 
ruby-1.8.7-p299 > Rational(3/7) <=> Rational(5/7)
 => -1 

但如果它们被评估为fixnums,则3/7返回零,而ruby不能将0与0(整数除法)进行比较

ruby-1.8.7-p299 > 3/7
 => 0 
ruby-1.8.7-p299 > 5/7
 => 0 
ruby-1.8.7-p299 > 3/7 <=> 5/7
 => 0 
ruby-1.8.7-p299 > 5/7 <=> 5/7
 => 0 
ruby-1.8.7-p299 > 8/7 <=> 5/7
 => 1 
ruby-1.8.7-p299 > 7/7 <=> 7/7
 => 0