【问题标题】:Rails4 : Model caching (low level caching)Rails4:模型缓存(低级缓存)
【发布时间】:2015-05-25 19:00:45
【问题描述】:
我正在尝试缓存 Active Record 查询的结果。
这是我的用例:
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
这里有两个问题:
- self.awesome_users_cached 不缓存结果并最终命中
- all_awesome_users 最终成为一个数组而不是活动记录,因此我无法从中过滤掉less_awesome_users。
有一个解决方案似乎不再适用于 Rails4:Rails cache with where clause
【问题讨论】:
标签:
ruby-on-rails
caching
ruby-on-rails-4
activerecord
【解决方案1】:
您不应该缓存 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)