当我在控制器的操作中进行以下调用时,我可以看到第一次加载该页面时,我在控制台输出中看到了输出“ posts hit the db”。
cache_key = "posts"
@posts = Rails.cache.fetch(cache_key, expires_in: 5.minutes) do
puts "posts hitting the db"
Post.include(:tags).where("post_status = 1").order("id desc")
end
如果我重新加载页面,则看不到“帖子击中数据库”的消息,但仍然可以看到类似的查询:
由PostsController#index作为HTML渲染处理 布局内的posts / index.html.erb /主发布后加载时间(0.5ms)SELECT “ posts”。*从“ posts”位置(post_status = 1)按ID desc排序 app / views / posts / index.html.erb:6标签加载(0.3ms)选择“标签”。* 在“标签”中的“标签”。“ id” = $ 1 [[“ id”,7]]↳ app / views / posts / index.html.erb:6呈现的帖子/index.html.erb 布局/帖子内(31.4ms)在87ms内完成200 OK(查看:62.6ms) | ActiveRecord:8.2毫秒)
这是因为它正在缓存@posts,但是由于实际上并未使用@posts对象,所以甚至没有进行db调用?那么,当查看页面执行@ posts.each时,它将命中数据库吗?
例如,如果我在视图页面中删除了所有html,那么它根本不会打入数据库。
答案 0 :(得分:3)
这样做的时候
Post.include(:tags).where("post_status = 1").order("id desc")
您实际上并不是在调用数据库。您正在创建ActiveRecord范围-这就是您要缓存的内容。如果要缓存数据库调用的结果,则需要执行以下操作:
cache_key = "posts"
@posts = Rails.cache.fetch(cache_key, expires_in: 5.minutes) do
puts "posts hitting the db"
Post.include(:tags).where("post_status = 1").order("id desc").all.to_a
end
相反,这使ActiveRecord实际上用表数据填充@posts。
答案 1 :(得分:1)
正如@bkimble所说,您需要添加.all
才能将查询转换为数据库调用。但是,由于Rails 4,.all
是延迟执行的。正如我在此Memcache guide for Rails中所解释的那样,您需要强制执行它,例如,通过添加.to_a
来将结果转换为数组。
您的代码将如下所示:
cache_key = "posts"
@posts = Rails.cache.fetch(cache_key, expires_in: 5.minutes) do
puts "posts hitting the db"
Post.include(:tags).where("post_status = 1").order("id desc").all.to_a
end