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

我正在尝试缓存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最终成为一个数组而不是活动Record,因此我无法从中过滤掉less_awesome_users。

有一个解决方案似乎不再适用于Rails4: Rails缓存与where子句

您永远不应该缓存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)