0

想象一下,我有 5 个标签:tag1,tag2...tag5. 如果我执行以下操作:

Rails.cache.fetch("all.tags") { Tag.all }

然后我写Rails.cache.fetch("all.tags")了,我看到了 5 个标签。如果我添加另一个标签,并尝试再次从缓存中获取,新标签也会被加载。这是为什么?

编辑:这是我的实际代码:

Rails.cache.fetch("autocomplete.#{term}") { puts "Cache miss #{term}"; Tag.starting_with(term) }

在哪里starting_with可以找到以某些字母开头的标签。这是我在控制台中得到的行为:

1.9.3p125 :046 > Rails.cache.read("autocomplete.ta")
  Tag Load (1.0ms)  SELECT "tags".* FROM "tags" WHERE (name like 'ta%')
 => [#<Tag id: 10, name: "tag1">, #<Tag id: 11, name: "tag2">, #<Tag id: 12, name: "tag3">, #<Tag id: 13, name: "tag4">]
1.9.3p125 :048 > Tag.create(name:"tag5")
   (0.2ms)  begin transaction
  SQL (1.0ms)  INSERT INTO "tags" ("name") VALUES (?)  [["name", "tag5"]]
   (150.9ms)  commit transaction
 => #<Tag id: 14, name: "tag5"> 
1.9.3p125 :049 > Rails.cache.read("autocomplete.ta")
  Tag Load (0.8ms)  SELECT "tags".* FROM "tags" WHERE (name like 'ta%')
 => [#<Tag id: 10, name: "tag1">, #<Tag id: 11, name: "tag2">, #<Tag id: 12, name: "tag3">, #<Tag id: 13, name: "tag4">, #<Tag id: 14, name: "tag5">] 
4

2 回答 2

1

这是不可能的 。

缓存作用于键/值对。

Rails.cache.fetch("all.tags") { Tag.all }

它将始终返回存储键 "all.tags" 的值。

您能否尝试读取是否存储在缓存中的值。然后添加新标签

Rails.cache.read("all.tags")

根据您的问题,我知道这不是答案,但我也很想知道它为什么会发生。

你还在用缓存设置做其他事情吗?

于 2012-04-11T07:06:10.177 回答
1

您没有显示代码,Tag.starting_with_term但我敢打赌它是一个范围或返回类似范围的东西,即类似于以下内容的东西

Tag.where(...)

Tag.all这与你最初的问题根本不同:Tag.all是一个数组,但上面是一个范围。范围是懒惰地评估的,仅当您在范围上调用要求范围是实际数组的方法时才从数据库请求行。

这里发生的是您正在缓存实际范围,而不是范围将选择的行。另一种看待它的方式是说,此时您正在缓存构成查询的条件,而不是查询结果。

当您从缓存中读取时,您的范围将从缓存中检索,并且尝试显示它的行为会强制 rails 对其进行评估。此评估发生在从缓存中检索范围之后,因此您始终可以获得新的结果。

最简单的事情是强制评估范围,即类似

Rails.cache.fetch('cache_key') { Tag.starting_with(term).all }
于 2012-04-11T08:13:23.077 回答