在这种情况下,请解释Rails缓存的行为

时间:2012-04-11 06:39:15

标签: ruby-on-rails caching

想象一下,我有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">] 

2 个答案:

答案 0 :(得分:1)

不可能。

缓存处理键/值对。

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

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

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

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

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

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

答案 1 :(得分:1)

你还没有展示Tag.starting_with_term的代码,但我敢打赌它是一个范围或者返回范围之类的东西,比如

Tag.where(...)

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

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

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

最简单的方法是强制评估范围,例如

Rails.cache.fetch('cache_key') { Tag.starting_with(term).all }