由于最近在将项目升级到 Rails,顺便将 Mongoid 从也从 3.1.4 升到 3.1.6,至于为什么,可以点击这里 升级 Mongoid 的一些配置 被除掉了, IndentityMap 就是之一, 然后官方给出的替代方式是使用 Query::Cache Middleware.
在配置文件添加 config.middleware.use(Mongoid::QueryCache::Middleware);
假如 我执行下面的操作:
def index
@users = UserMongo.all
end
然后其他的地方
if @users.present? #----> 标记A
...其他操作
@users.each do |p| #-----> 标记B
....
end
end
执行的'标记 B'的时候,会抛出异常
QUERY CACHE database=tianji collection=users selector={}
TypeError: no implicit conversion of String into Integer
from /home/andy/Documents/mongoid/lib/mongoid/factory.rb:40:in `[]'
通过 pry 追踪源码
module Mongoid
module QueryCache
module Cacheable
def with_cache
return yield unless QueryCache.enabled?
return yield if system_collection?
key = cache_key
if QueryCache.cache_table.has_key?(key)
instrument(key) { QueryCache.cache_table[key] }
else
value = yield
QueryCache.cache_table[key] = value
end
end
end
end
发现 在执行'标记 A' @users.present?, QueryCache.cache_table[key] 的值已经被设置上了
puts QueryCache.cache_table -->
{["tianji", "users", {}]=>{"_id"=>158}}
然后在 执行'标记 B’的时候 其实 是对 'A'的结果 进行遍历,所以 就会报错。
我认为 这是 QueryCache 的一个 bug,没有很好区分好 QueryCache.cache_table 的 key。
补充一下 key 的选取是这样子的:
def cache_key
[ operation.database, operation.collection, operation.selector ]
end
大家在升级 Mongoid 的过程中,有没有遇到同样的问题; 实在不行,我可能会先覆盖部分 Mongoid 源码。