在api调用期间向activerecord对象添加数组

xxhby3vn  于 2021-09-29  发布在  Java
关注(0)|答案(2)|浏览(307)

我有两个班叫教室和学生。他们有一种多对多的关系,因为教室可以有许多学生,但学生也可以属于许多教室。当我调用api来获取一个部分教室时,我还想抓取属于该教室的所有学生(通过Student教室联接表),并将他们添加到我从api返回的教室activerecord对象中。
如果我在控制器中返回响应之前使用binding.pry i暂停执行,@教室.students将按预期返回一组学生记录。然而,当@教室被发送到前端时,它将从学生数组中剥离。我做错了什么?
课堂

class Classroom < ApplicationRecord
    has_many :student_classrooms
    has_many :students, through: :student_classrooms
    def get_classroom_students(classroom_id)
       StudentClassroom.where(classroom_id: classroom_id)
    end
end

控制器

def show
    students = @Classroom.get_classroom_students(@Classroom.id)
    # somehow add students to @Classroom ActiveRecord object
    render json: @Classroom
  end
sqserrrh

sqserrrh1#

这永远不会让学生回到前端。当你添加 binding.pry 在控制器上测试,你仍然有 ActiveRecord 具有 students 方法已定义,但将其传递到前端时,会将其转换为json:

render json: @Classroom

所以json没有学生数组。要解决此问题,您可以在show action上尝试以下操作:

def show
  render json: @Classroom.as_json(include: students)
end

这将包括 students 在json中,您将传递到前端。
如果您希望将此行为设置为默认行为,即 Classroom 对象转换为json,然后包含 students 你可以加上 as_json 方法论 Classroom 像这样的课程:

def as_json(options = {})
  super({ include: :students }.merge(options))
end

现在,每当 Classroom 对象转换为json,它将包括学生。示例:


# this will automatically include the students in your controller action

render json: @Classroom

# this will also have the students included

Classroom.last.to_json
mqxuamgl

mqxuamgl2#

当你打电话的时候 render 没有神奇的事情发生:在响应体中发送之前,您的课堂对象将被序列化。
ar模型的默认json序列化大致上是属性的散列-没有关联,没有示例方法等。您可以通过重新定义 as_json 对于模型,正如另一个答案所建议的,但这通常是一个坏主意-对于不同的端点和/或场景,您可能(而且很可能会)需要不同的序列化,因此在模型中只使用一个硬编码将迫使您添加越来越多的黑客攻击。
更好的方法是将序列化与业务逻辑解耦——这就是序列化程序发挥作用的地方。看看https://github.com/jsonapi-serializer/jsonapi-serializer 例如,这就是您需要以干净且可维护的方式解决任务的原因。
只需定义一个序列化程序

class ClassroomSerializer
  include JSONAPI::Serializer

  attributes <attributes you would like to expose>
  has_many :students
end

(只是一个草稿-请参阅文档以释放所有的力量:))您可以使用以下简单的方法:

def show
  render json: ClassroomSerializer.new(@classroom).serializable_hash
end

相关问题