Rails4:模型缓存(低级缓存)

时间:2015-03-22 20:04:46

标签: ruby-on-rails caching ruby-on-rails-4 activerecord

我正在尝试缓存Active Record Query的结果。

这是我的用例:

User.rb
  def self.awesome_users_cached
    Rails.cache.fetch("awesome_users") { where(awesome: true) }
  end

UsersController
  def index
    all_awesome_users  = User.awesome_users_cached
    less_awesome_users = User.where(less_awesome_user:true).pluck(:id)
    @users             = all_awesome_users.where.not(id: less_awesome_users)
  end

以下是2个问题:

  1. self.awesome_users_cached不会缓存结果并最终点击
  2. all_awesome_users以数组结尾而不是活动记录,因此我无法从中过滤掉less_awesome_users。
  3. 有一个解决方案似乎不再适用于Rails4:Rails cache with where clause

1 个答案:

答案 0 :(得分:3)

您永远不应该缓存ActiveRecord实例或复杂对象。相反,您应该缓存简单的原始值,例如记录的主键。

在您的情况下,还有一个问题。 where(awesome: true)返回范围,而不是查询结果。因为范围是惰性执行的,所以除了始终执行查询之外,您实际上从不缓存任何内容。

如果要缓存查找,请执行繁重查询并返回受影响记录的ID。然后执行第二个查询,通过id获取记录。您将运行2个查询,但第一个查询(最昂贵的查询)将在第一次之后缓存。

def self.awesome_users_cached
  ids = Rails.cache.fetch("awesome_users") { where(awesome: true).pluck(:id) }
  find(ids)
end

您可以缓存第一个查询的查找,但正如我之前提到的,这不是一个好主意。

def self.awesome_users_cached
  Rails.cache.fetch("awesome_users") { where(awesome: true).to_a }
end

您还可以使用其他查询方法,以便您可以轻松地将其他条件链接到缓存查询。

def self.awesome_users_cached
  ids = Rails.cache.fetch("awesome_users") { where(awesome: true).pluck(:id) }
  where(id: ids)
end

awesome_users_cached.where.not(id: same_company_users)