Ruby 2.2.6 + Rails 4.1.16环境下保存含JSON字段模型时出现TypeError问题求助
解决Rails 4.1 + PostgreSQL 11下JSON字段保存的TypeError问题
这个问题的核心是Rails 4.1的store宏默认序列化方式与PostgreSQL JSON字段类型不兼容,再加上参数白名单配置的小问题,导致保存时触发类型转换错误。我来一步步帮你解决:
问题根源分析
在Rails 4.1中,store宏是为text类型字段设计的——它默认把哈希序列化成YAML字符串存储。但你把它用在了PostgreSQL的json类型字段上,这就产生了冲突:
- Rails尝试把哈希转成YAML字符串,而PostgreSQL的
json字段期望的是标准JSON格式数据 - 同时你的参数白名单把
key1/key2等单独permit,没有嵌套在description下,进一步加剧了数据结构的混乱
这就是为什么实例化能成功,但调用save时触发typeerror: no implicit conversion of hash into string的原因。而Rails 6.1对PostgreSQL JSON字段的支持已经做了优化,自动适配了序列化逻辑,所以不会报错。
解决方案
方案1:修改store宏的序列化方式为JSON
既然你的字段是PostgreSQL json类型,我们让store用JSON来序列化哈希,而不是默认的YAML:
- 更新模型代码:
class Jason < ApplicationRecord store :description, accessors: [:key1, :key2, :watapak], coder: JSON end
- 修正参数白名单,把accessors字段嵌套在
description下:
def jason_params params.require(:jason).permit(:name, description: [:key1, :key2, :watapak]) end
- 保存时按嵌套结构传参:
# 直接传入嵌套的description哈希 jason = Jason.new(name: "Jason John", description: {key1: "abcd", key2: "efgh"}) jason.save
如果是表单提交,字段命名要改成jason[description][key1]这种格式。
方案2:放弃store宏,直接操作JSON字段
Rails 4.1已经原生支持PostgreSQL JSON字段作为哈希访问,如果你不需要store带来的accessors语法糖,可以直接移除它:
- 简化模型代码:
class Jason < ApplicationRecord # 移除store宏,直接用description哈希 end
- 同样使用嵌套的参数白名单:
def jason_params params.require(:jason).permit(:name, description: [:key1, :key2, :watapak]) end
- 保存时直接操作
description哈希:
jason = Jason.new(name: "Jason John") jason.description[:key1] = "abcd" jason.description[:key2] = "efgh" jason.save
验证效果
调整后,Rails会正确把哈希序列化成JSON格式字符串传给PostgreSQL的json字段,不会再触发类型转换错误。你可以对比生成的SQL,应该会看到description参数是标准的JSON格式字符串,和你之前Rails 4.1环境的SQL类似,但不会有类型转换冲突。
内容的提问来源于stack exchange,提问作者Farr
相关产品推荐
相关产品推荐

