Rails 请问 Rails 3.2.11 中 fresh_when 的用法

wuwx · 2013年01月10日 · 最后由 huacnlee 回复于 2014年05月30日 · 4642 次阅读

按照 huacnlee 的 BLOG 上的用法,以及官方 guides 的用法,加了一行代码:

def index
  @topics = Topic.includes(:user).page(params[:page]).reverse_order
  fresh_when(:etag => [@topics])
  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @topics }
  end
end

然后很 happy 地等待浏览器 304 相应,可是刷新来刷新去,发现每次 ETag 值都是变化的 每次请求都是 200 响应,一点都看不出来有被 Cache 了,这个是为什么呢

fresh_when 你覆盖过么?

#1 楼 @huacnlee 木有覆盖哇,没有重写过这个方法…… 不过发现一个问题,如果是单个对象就可以返回 304,列表就不行

#2 楼 @wuwx 你先打印 Log 出来看看,会不会是列表的数据每次都不同

#1 楼 @huacnlee log 来了

Started GET "/topics" for 127.0.0.1 at 2013-01-11 15:07:51 +0800
Processing by TopicsController#index as HTML
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  Rendered topics/_form.html.erb (3.7ms)
  Topic Load (0.1ms)  SELECT "topics".* FROM "topics" ORDER BY "topics"."id" DESC LIMIT 30 OFFSET 0
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (1)
   (0.1ms)  SELECT COUNT(*) FROM "comments" WHERE "comments"."topic_id" = 1
   (0.1ms)  SELECT COUNT(*) FROM "flowers" WHERE "flowers"."topic_id" = 1
  Rendered topics/_topic.html.erb (4.3ms)
  Rendered topics/index.html.erb within layouts/topics (11.9ms)
  User Load (0.2ms)  SELECT "users".* FROM "users" LIMIT 10
  Rendered users/_user.html.erb (1.0ms)
  Rendered layouts/application.html.erb (3.7ms)
Completed 200 OK in 22ms (Views: 19.8ms | ActiveRecord: 1.0ms)


Started GET "/assets/application.css" for 127.0.0.1 at 2013-01-11 15:07:51 +0800
Served asset /application.css - 304 Not Modified (4ms)


Started GET "/assets/application.js" for 127.0.0.1 at 2013-01-11 15:07:51 +0800
Served asset /application.js - 304 Not Modified (2ms)


Started GET "/topics" for 127.0.0.1 at 2013-01-11 15:07:52 +0800
Processing by TopicsController#index as HTML
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  Rendered topics/_form.html.erb (3.8ms)
  Topic Load (0.2ms)  SELECT "topics".* FROM "topics" ORDER BY "topics"."id" DESC LIMIT 30 OFFSET 0
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (1)
   (0.1ms)  SELECT COUNT(*) FROM "comments" WHERE "comments"."topic_id" = 1
   (0.1ms)  SELECT COUNT(*) FROM "flowers" WHERE "flowers"."topic_id" = 1
  Rendered topics/_topic.html.erb (4.5ms)
  Rendered topics/index.html.erb within layouts/topics (12.3ms)
  User Load (0.1ms)  SELECT "users".* FROM "users" LIMIT 10
  Rendered users/_user.html.erb (1.1ms)
  Rendered layouts/application.html.erb (3.0ms)
Completed 200 OK in 22ms (Views: 19.6ms | ActiveRecord: 1.0ms)


Started GET "/assets/application.css" for 127.0.0.1 at 2013-01-11 15:07:52 +0800
Served asset /application.css - 304 Not Modified (4ms)


Started GET "/assets/application.js" for 127.0.0.1 at 2013-01-11 15:07:52 +0800
Served asset /application.js - 304 Not Modified (2ms)


我之前试用过这个方法,也发现有这样的问题

#4 楼 @wuwx 我少打了几个字... 我的意思是让你自己把 @topics 打印出来看看每次的内容是否是相同的,简单方法直接做个 MD5 看看每次的值是不是相同的

不用发布上来,你确定内容是否有变化就好了

@topics = Topic.includes(:user).page(1).reverse_order
Digest::MD5.hexdigest(@topics)

报告错误:TypeError: can't convert ActiveRecord::Relation into String

#8 楼 @huacnlee 果然好使了,厉害

最后把控制器改成这样了:

def index
  @topics = Topic.includes(:user).page(params[:page]).reverse_order.all
  fresh_when(:etag => [@topics])
end

@huacnlee fresh_when 怎么搞能把 cell 里的数据也计算上

另外 @huacnlee 刚才发了帖子后 帖子创建成功。这个 notice 一直在我发的帖子上,并且,304 致使阅读次数也不变化了

#12 楼 @huobazi 这个是我忘了把 flash 加入 etag 的计算里面

#11 楼 @huobazi 这个就麻烦了,还没想过

@wuwx @huacnlee 上面处理有一个问题想问一下,@topics = Topic.includes(:user).page(1).reverse_order 这是一个延迟查询,@topics = Topic.includes(:user).page(params[:page]).reverse_order.all 这是真正去查询了数据了,如果页面做了片段缓存,那么 @topics = Topic.includes(:user).page(1).reverse_order 将不会查询数据,但是进行了内容的传输,没有用到本地浏览器缓存,@topics = Topic.includes(:user).page(params[:page]).reverse_order.all 也查了数据库,但是用到了本地浏览器缓存

@wuwx @huacnlee 为什么 ActiveRecord::Relation 每次查询出来的不一样啊?

@wuwx @huacnlee 说的具体一点就是,Digest::MD5.hexdigest(ActiveRecord::Relation) 每次的结果不一样

@wuwx @huacnlee 我想问一下为什么不一样

#18 楼 @josh_sulin 不一样应该是每次的 AREL 的 object_id 不同导致的。

fresh_when 并不是对整个内容做 MD5 的,而是挑了一些特别的属性,比如 Model 的 updated_at, id 等

需要 登录 后方可回复, 如果你还没有账号请 注册新账号