如何根据对象与其他对象属性的关系设置对象的属性?

时间:2012-07-10 23:58:20

标签: ruby-on-rails ruby activerecord attributes

我有一个简单的高尔夫应用程序,每个玩家都有:total_score:current_place属性。我希望Rails根据该玩家的:current_place是高于还是低于其他玩家来定义每个玩家的:total_score属性。

换句话说,如果有两个玩家,一个有:total_score => 5而另一个有:total_score => 4我想让Rails成为第一个玩家:current_place => 1,另一个玩家:current_place => 2玩家的:current_place,依此类推。我基本上希望它根据:total_score列的下降来定义{{1}}值。

1 个答案:

答案 0 :(得分:0)

你可以通过观察者实现这一点,当一个玩家被保存时启动和sql查询,然后更新属性(使用update_attribute,因此它不会触发回调)。但这将是一个不太高效的解决方案,也可能存在竞争条件问题。

另一种解决方案是在某个地方实现相同的查询,并使模型的current_place函数访问结果。这也可以很容易地缓存

代码:

class Player < ActiveRecord::Base
  def current_place
    self.class.current_place(self.id) if self.id
  end

  def self.all_places
    rank = {}
    pos = 0
    self.order_by('total_score desc').each{|p| rank[p.id] = (pos += 1)}
    rank
  end

  def self.current_place(id)
    all_places[id]
  end
end

我没有测试它,但我想这样的事情应该有效。要获得缓存的部分,您只需将all_places包装在Rails.cache.fetch块中,并在每次更新玩家总分时使其过期