Rails4.2.7升级到6.0.4.1后Postgres jsonb字段返回空哈希问题求助
问题根因
- 版本适配冲突:Rails 4.2对PostgreSQL的jsonb字段原生支持不完善,需要配合
store+自定义序列化器实现读写;Rails 5.0及以后版本原生支持jsonb字段的自动序列化/反序列化,无需额外配置store,两者叠加导致处理逻辑冲突。 - 未声明key被过滤:
store方法设计用于将指定属性序列化存入单个字段,Rails 5.0+的store逻辑会自动过滤未在accessors参数中声明的key,你代码中声明的accessor为小写的author、version,但实际存储的key为大写的AUTHOR、VERSION以及未声明的OS,所有key都被过滤,最终返回空Hash。
解决方案
方案1:移除store配置,使用Rails原生jsonb支持(推荐)
直接删除模型中store相关的配置代码即可,Rails会自动完成jsonb字段的读写映射:
class TestTable < ActiveRecord::Base # 删掉以下两行 # DATA_ATTRIBUTES = [ :author, :version ] # store :data, accessors: DATA_ATTRIBUTES, coder: ActiveSupportJsonProxy end
如果需要保留原有小写属性的调用方式(比如业务代码中已经大量使用test_table.author而非test_table.data['AUTHOR']),可以手动添加访问方法:
class TestTable < ActiveRecord::Base def author data['AUTHOR'] end def author=(val) data['AUTHOR'] = val end def version data['VERSION'] end def version=(val) data['VERSION'] = val end end
调整后不需要再保留ActiveSupportJsonProxy自定义序列化类,可以直接删除。
方案2:适配现有store逻辑(仅用于临时兼容旧代码)
如果暂时不想调整业务层调用,可以将store替换为Rails原生针对json/jsonb字段设计的store_accessor,同时映射大小写key:
class TestTable < ActiveRecord::Base store_accessor :data, AUTHOR: :author, VERSION: :version end
额外注意
你添加data字段的迁移中设置默认值的写法不符合Rails 6+的jsonb字段规范,建议修改为:
change_column_default :test_table, :data, to: {}
避免默认值被错误序列化为字符串存入数据库。
内容的提问来源于stack exchange,提问作者raj_acharya
相关产品推荐
相关产品推荐

