升级至Rails 7.1后从Redis缓存读取Active Record模型报错
Rails 7.1.3.2 升级后 Redis 缓存 Active Record 模型的属性读取问题
问题背景
将Rails从7.0.8升级至7.1.3.2后,使用Redis缓存Active Record(AR)模型时出现异常:读取缓存中的模型实例时,除id外的其他属性无法访问,报错提示未知方法。缓存代码示例:
Rails.cache.fetch("key_name") { Ar_Model[some_key] }
复现步骤与现象
第一个控制台(正常场景):
model = Rails.cache.fetch("key_name") { Ar_Model[some_key] } model.class => Ar_Model(id: integer, name: string) model.name => "some_name"所有属性均可正常读取。
第二个控制台(异常场景):
model = Rails.cache.fetch("key_name") model.class => Ar_Model(id: integer, name: string) model.id => some_id model.name => Error! Unknown method 'name' for Ar_Model()读取非
id属性时报错。特殊修复现象:在第二个控制台执行
Ar_Model.first后,无需重新加载缓存模型即可正常读取所有属性:model = Rails.cache.fetch("key_name") model.class => Ar_Model(id: integer, name: string) model.id => some_id model.name => Error! Unknown method 'name' for Ar_Model() Ar_Model.first model.name => "some_name"
问题原因
Rails 7.1对Active Record的序列化/反序列化机制做了优化,当模型类在当前进程中未完成初始化(未执行过查询、未加载属性定义)时,反序列化缓存中的模型实例只会加载主键属性的访问器方法。而执行Ar_Model.first这类操作会触发模型类的初始化,加载所有属性的访问器,因此之后能正常读取属性。
解决方案
方案1:缓存属性哈希而非模型实例
避免直接缓存AR实例,改为缓存属性哈希,读取时再构建模型:
# 写入缓存 Rails.cache.fetch("key_name") { Ar_Model[some_key].attributes } # 读取缓存 model = Ar_Model.new(Rails.cache.fetch("key_name")).tap(&:readonly!)
如果需要包含关联数据,可使用serializable_hash(include: [:关联名])替代attributes。
方案2:预加载模型类初始化
在读取缓存前,主动触发模型类的属性加载,确保访问器已定义:
# 读取缓存前执行,触发模型属性初始化 Ar_Model.columns_hash model = Rails.cache.fetch("key_name")
也可以在应用启动时预加载所有AR模型,比如在初始化脚本中添加:
Rails.application.eager_load!
方案3:统一缓存序列化版本
确保应用使用Rails 7.1的缓存序列化格式,在config/application.rb中配置:
config.active_record.cache_format_version = 7.1
注意:如果缓存中存在旧版本格式的数据,需先清理缓存,否则反序列化仍会异常。
内容的提问来源于stack exchange,提问作者S. Chekan
相关产品推荐
相关产品推荐

