You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails中Pagy Gem非首页面分页HTTP缓存未失效问题

解决Ruby on Rails中Pagy分页页面HTTP缓存不更新的问题

问题根源

你当前的代码里,@records是分页后的数据集。当非首页的记录更新时,如果当前分页页里没有包含这条更新的记录,@records.maximum(:updated_at)就不会发生变化,导致fresh_when生成的ETag和Last-Modified值不变,浏览器会继续使用旧缓存,看不到更新后的数据。而首页正常是因为更新的记录刚好在首页,触发了max值变化。

修复方案

核心是用完整数据集的最新更新时间来生成缓存标识,同时把页码加入ETag区分不同分页页的缓存:

  1. 先保留未分页的完整数据集,不要直接把查询结果传给pagy
  2. 用完整数据集的maximum(:updated_at)作为缓存判断依据
  3. 把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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 08:27:17