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

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(错误触发源)

成因分析
  1. Rails 7.x对ActiveModel/ActiveRecord的属性序列化逻辑做了重构,ActiveModel::Type::Value#as_json方法在7.1.4版本中不再处理ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb这类类型实例的序列化。
  2. Audited gem在处理jsonb类型的audited_changes字段时,错误地将类型对象(而非字段值)包含进了待序列化的结构中,导致调用as_json时触发未定义方法的错误。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:18:25