Rails升级至7.1.4后PostgreSQL jsonb字段报NoMethodError求助
问题:Rails 5.2升级至7.1.4后PostgreSQL jsonb字段序列化异常
项目从Rails 5.2升级到7.1.4后,使用Audited gem创建审计记录时,序列化PostgreSQL jsonb字段触发NoMethodError,错误指向ActiveModel::Type::Value#as_json调用ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb实例时出错。
错误信息
NoMethodError: NoMethodError from /home/kevin/.rvm/gems/ruby-3.3.4/gems/activemodel-7.1.4/lib/active_model/type/value.rb:145:in `as_json'
触发场景
序列化包含ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb类型实例的哈希结构时出现问题,涉及ActiveModel::Attribute::FromDatabase和ActiveModel::Attribute::FromUser两种属性类型。
触发代码:
Audited::Audit.create(auditable: admin, user: admin, action: 'update', audited_changes: {this: [nil, 'something']}, comment: 'because', version: 1)
版本信息
- Ruby 3.3.4
- Rails 7.1.4
- PG 1.5.7
- Audited 5.7.0(错误触发源)
成因分析
- Rails 7.x对ActiveModel/ActiveRecord的属性序列化逻辑做了重构,
ActiveModel::Type::Value#as_json方法在7.1.4版本中不再处理ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb这类类型实例的序列化。 - Audited gem在处理jsonb类型的
audited_changes字段时,错误地将类型对象(而非字段值)包含进了待序列化的结构中,导致调用as_json时触发未定义方法的错误。 - Rails 5.2的序列化逻辑对这类类型实例有兼容处理,但升级后该兼容逻辑被移除,暴露了Audited的潜在问题。
解决方法
方法一:升级Audited gem到兼容Rails 7.1的版本
升级Audited到适配Rails 7.x序列化逻辑的最新版本(如>=5.8.0,需参考官方更新日志确认),新版本已修复此类兼容性问题,避免将类型对象混入待序列化数据。
方法二:手动补丁修复Audited序列化逻辑
若暂时无法升级gem,可在项目中添加初始化补丁,确保仅序列化字段值而非类型对象:
# config/initializers/audited_jsonb_patch.rb module Audited class Audit < ActiveRecord::Base def audited_changes=(value) super(value.is_a?(Hash) ? value.deep_dup : value) end def as_json(options = {}) json = super(options) if json['audited_changes'].is_a?(Hash) json['audited_changes'] = json['audited_changes'].except('type', 'original_attribute') end json end end end
方法三:临时兼容Rails类型序列化逻辑
为ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb添加as_json方法定义,避免序列化出错:
# config/initializers/active_model_type_patch.rb ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb.class_eval do def as_json(options = {}) name.to_s end end
内容的提问来源于stack exchange,提问作者Kinitawowi
相关产品推荐
相关产品推荐

