Rails中如何用as_json的include选项关联多层级关联表获取数据
多层关联as_json写法
你要嵌套加载多层关联,直接给as_json的include参数传哈希结构即可,示例代码如下:
# HogesController 中修改as_json部分 hoges = Hoge.index( params[:keyword], nil, params[:hoge_category_id], params[:offset].to_i, 10 ) .includes(hoge_category: :big_hoge_category) # 预加载关联避免N+1查询 .as_json( only: [:id, :title, :message, :created_at], # 按需指定返回的Hoge字段 include: { hoge_category: { only: [:id, :name], # 按需指定HogeCategory返回字段 include: { big_hoge_category: { only: [:id, :name] # 按需指定BigHogeCategory返回字段 } } } } ) render status: 200, json: { hoges: hoges }
这里额外加了includes是因为Searchkick返回的结果默认不会预加载关联,直接序列化会触发N+1查询,加了之后只会执行3次查询(Hoge、HogeCategory、BigHogeCategory各一次),性能提升非常明显。
更优的序列化方案
如果后续关联逻辑会越来越复杂,更推荐用专门的序列化工具维护返回结构,避免控制器里的as_json越写越臃肿,可选方案有两种:
- Jbuilder
Rails官方默认支持的序列化方案,直接在视图层定义JSON结构,示例:
新建app/views/hoges/index.json.jbuilder,写入如下内容:
json.hoges @hoges do |hoge| json.extract! hoge, :id, :title, :message, :created_at json.hoge_category do json.extract! hoge.hoge_category, :id, :name json.big_hoge_category do json.extract! hoge.hoge_category.big_hoge_category, :id, :name end end end
控制器只需要给@hoges赋值即可,不需要调用as_json:
@hoges = Hoge.index( params[:keyword], nil, params[:hoge_category_id], params[:offset].to_i, 10 ) .includes(hoge_category: :big_hoge_category) render status: 200
- ActiveModel::Serializers
更面向对象的序列化方案,每个模型对应一个序列化器,复用性更强,适合接口结构统一的项目。
额外优化提示
你当前的Hoge.index方法里定义的where是空的,传进来的hoge_category_id参数没有生效,如果需要按分类过滤Hoge,可以补充到where条件里:
def self.index(keyword, connect_id, hoge_category_id, offset, limit) where = {} where[:hoge_category_id] = hoge_category_id if hoge_category_id.present? # 新增分类过滤 # 原有搜索逻辑不变 end
内容的提问来源于stack exchange,提问作者Hinoarashi
相关产品推荐
相关产品推荐

