如何在Rails 5.2.4的Postgres Arel查询中提取JSON元素?
解决方法
1. 问题根源
你的Parameter模型里name字段被ActiveRecord映射为JSON/Hash类型,但查询时用as name把字符串结果覆盖了这个字段。ActiveRecord会尝试把返回的字符串解析成JSON,而单个字符串(比如"New")不是合法的JSON对象,解析失败后就返回null。
2. 方案一:换个查询别名
别用name当别名,换个比如english_name,让ActiveRecord直接返回字符串:
原生SQL写法
options = Parameter.select( :id, :code, :sort_code, :property, "(name ->> 'en') as english_name" ).where(parameters_list_id: 3)
Arel写法
name_col = Parameter.arel_table[:name] english_name = name_col.send(:'->>', 'en').as('english_name') options = Parameter.select( :id, :code, :sort_code, :property, english_name ).where(parameters_list_id: 3)
之后用record.english_name就能拿到对应的英文名称。
3. 方案二:模型里加方法(推荐)
在Parameter模型里写个实例方法,直接从JSON字段取对应语言的值,不用在查询里折腾:
class Parameter < ApplicationRecord def name_in(locale = I18n.locale) name[locale.to_s] if name.present? end end
查询时直接拿全字段,之后调用方法:
options = Parameter.where(parameters_list_id: 3) options.each do |param| puts param.name_in('en') # 输出英文名称 end
这种方式符合Rails约定,后续改语言也方便,直接传不同locale就行。
4. 方案三:用Rails内置JSON查询API(Rails 5+)
Rails 5及以上支持直接用ActiveRecord的JSON方法,不用写原生SQL:
options = Parameter.select( :id, :code, :sort_code, :property, Parameter.arel_table[:name].get_text('en').as('english_name') ).where(parameters_list_id: 3)
get_text对应PostgreSQL的->>运算符,返回文本类型,别名避免冲突。
内容的提问来源于stack exchange,提问作者user1185081
相关产品推荐
相关产品推荐

