Ruby on Rails中Pagy Gem非首页面分页HTTP缓存未失效问题
解决Ruby on Rails中Pagy分页页面HTTP缓存不更新的问题
问题根源
你当前的代码里,@records是分页后的数据集。当非首页的记录更新时,如果当前分页页里没有包含这条更新的记录,@records.maximum(:updated_at)就不会发生变化,导致fresh_when生成的ETag和Last-Modified值不变,浏览器会继续使用旧缓存,看不到更新后的数据。而首页正常是因为更新的记录刚好在首页,触发了max值变化。
修复方案
核心是用完整数据集的最新更新时间来生成缓存标识,同时把页码加入ETag区分不同分页页的缓存:
- 先保留未分页的完整数据集,不要直接把查询结果传给pagy
- 用完整数据集的
maximum(:updated_at)作为缓存判断依据 - 把
params[:page]加入ETag,确保不同页码的缓存独立
修改后的代码示例:
# 先获取未分页的完整数据集(替换成你的实际查询条件) @all_records = Record.active # 比如你的业务查询 @pagy, @records = pagy(@all_records, items: 8) # 基于完整数据集的最新更新时间 + 页码生成缓存标识 latest_update = @all_records.maximum(:updated_at) fresh_when etag: [latest_update, params[:page]], last_modified: latest_update, public: true
性能优化(可选)
如果数据量较大,频繁调用maximum(:updated_at)会增加数据库查询开销,可以用Rails缓存来缓存这个值:
@all_records = Record.active @pagy, @records = pagy(@all_records, items: 8) # 缓存最新更新时间,1分钟过期(可根据业务调整) latest_update = Rails.cache.fetch("records_latest_update", expires_in: 1.minute) do @all_records.maximum(:updated_at) end fresh_when etag: [latest_update, params[:page]], last_modified: latest_update, public: true
为什么之前加页码没用?
你之前尝试把页码拼接进ETag,但因为用的是分页后@records的maximum(:updated_at),当更新的记录不在当前分页页时,这个max值不会变化,所以ETag整体还是和旧缓存一致,浏览器不会触发刷新。现在改用完整数据集的max值,只要任何记录更新,所有分页页的ETag都会变化,缓存就会自动失效。
内容的提问来源于stack exchange,提问作者habib
相关产品推荐
相关产品推荐

