Rails 7中如何在jsonapi-serializer中展开嵌套关联
解决方案
方案一:遵循JSON:API规范,展示完整关联资源
jsonapi-serializer 默认遵循 JSON:API 规范,关联数据会放在 relationships 中,完整资源则存入 included 数组。要实现展开关联的效果,只需两步操作:
- 更新AuthorSerializer,指定书籍序列化器
class AuthorSerializer include JSONAPI::Serializer attributes :id, :fname, :lname # 明确关联对应的序列化器,确保正确渲染书籍字段 has_many :books, serializer: BooksSerializer end
- 控制器渲染时添加
include参数
在index和show方法中,渲染序列化器时传入include: [:books],触发关联资源的展开:
# GET /authors def index @authors = Author.includes(:books).all render json: AuthorSerializer.new(@authors, include: [:books]) end # GET /authors/1 def show render json: AuthorSerializer.new(@author, include: [:books]) end
同时修正set_author方法,预加载书籍避免N+1查询:
def set_author @author = Author.includes(:books).find(params[:id]) end
返回的JSON会包含included数组,里面是完整的书籍信息,符合JSON:API规范,且不会产生额外数据库查询。
方案二:自定义嵌套字段(不遵循JSON:API规范)
如果希望直接将书籍的指定字段嵌套在作者的attributes中,而非使用included结构,可以自定义序列化属性:
class AuthorSerializer include JSONAPI::Serializer attributes :id, :fname, :lname, :books_summary # 自定义方法返回需要的书籍字段 def books_summary object.books.map do |book| { id: book.id, name: book.name, release_year: book.release_year # 按需添加其他字段,比如:genre、:price等 } end end end
控制器无需修改(确保已用includes(:books)预加载),渲染后作者的attributes里会多出books_summary字段,包含指定的书籍信息,同样不会触发额外查询。
额外优化
控制器的create和update方法当前直接渲染@author,未使用序列化器,建议统一调整,同时修正原代码中的笔误:
# POST /authors def create @author = Author.new(author_params) # 原代码中hospital_params为笔误,需改为author_params if @author.save render json: AuthorSerializer.new(@author), status: :created, location: @author else render json: @author.errors, status: :unprocessable_entity end end # PATCH/PUT /authors/1 def update if @author.update(author_params) render json: AuthorSerializer.new(@author) else render json: @author.errors, status: :unprocessable_entity end end
内容的提问来源于stack exchange,提问作者Ese10
相关产品推荐
相关产品推荐

