Rails计数器缓存

时间:2013-05-08 03:02:03

标签: ruby-on-rails ruby ruby-on-rails-3

我有一个带有多个计数器缓存的数据库模式。我不想将计数器缓存分布在许多表中,而是希望有一个名为user_counters的表,其中包含所有各种计数器缓存。我将使用如下方法从服务对象更新这些缓存:

def update_user_counter(column, user_id)
  UserCounter.increment_counter(column, user_id)
end

但是,关联用户的UserCounter记录很可能与用户没有相同的ID。我想做的是这样的事情:

def update_user_counter(column, user_id)    
  UserCounter.increment_counter(column, UserCounter.where('user_id = "#{user_id}"')
end

有关如何实现这一目标的任何想法?谢谢!

1 个答案:

答案 0 :(得分:2)

如果这些是与用户关联的10个属性,是否有任何理由不让它们成为用户模型的一部分?如果是这种情况,下面的代码仍然可以工作(只需将方法部分用户而不是UserCounter)。

如果你想按照自己的方式实现它,我首先要确保你的user_counters表有一个user_id的索引(因为Rails对于添加索引和FK是愚蠢的)。

然后,您可以这样做(将“列”作为符号传递):

class UserCounter < ActiveRecord::Base
  #other code

  def self.update_user_counter(column, user_id)
    counter = UserCounter.find_by_user_id(user_id)
    counter.update_attribute(column, counter.read_attribute(column) + 1)
    counter.save!
  end
end

在你的其他模特中:

class SomeOtherModel < ActiveRecord::Base
  #Model code

  def update_counter(user)
    UserCounter.update_user_counter(:this_column, user.id)
  end
end

此解决方案(或使用update_counter方法)都需要两个数据库命中,一个用于查找,另一个用于更新。如果您需要速度,可以直接在SQL中编写:

query = "UPDATE user_counters SET #{column} = #{column} + 1 WHERE user_id = #{user_id};"
ActiveRecord::Base.connection.execute(query);

这假设user_id上的user_counters是唯一的。