Ruby on rails 呈现连接模型及其关联模型的JSON对象

Ruby on rails 呈现连接模型及其关联模型的JSON对象,ruby-on-rails,ruby,json,activerecord,custom-object,Ruby On Rails,Ruby,Json,Activerecord,Custom Object,在Rails(4.1.5/ruby 2.0.0p481/win64)应用程序中,我在学生和课程之间有一个多对多关系,并有一个表示关联的联接模型StudentCourse,还有一个名为Start的附加属性(默认设置为“false”) 我还在联接表中添加了一个索引,由student\u id和course\u id组成,并设置了一个唯一的检查,如下所示 t.index [:student_id, :course_id], :unique => true, :name => 'by_stu

在Rails(4.1.5/ruby 2.0.0p481/win64)应用程序中,我在学生和课程之间有一个多对多关系,并有一个表示关联的联接模型StudentCourse,还有一个名为Start的附加属性(默认设置为“false”)

我还在联接表中添加了一个索引,由student\u id和course\u id组成,并设置了一个唯一的检查,如下所示

t.index [:student_id, :course_id], :unique => true, :name => 'by_student_and_course'
我希望它是一个复合主键,但由于rails中没有复合主键(不使用gem),我还添加了一个名为id的主键:

t.column :id, :primary_key
现在我看到关联是通过以下操作创建的:

Student.first.courses.create(:name => "english")

当然可以

+----+----------+------------------+
| id | name     | description      |
+----+----------+------------------+
| 1  | english  | desc. here       |
| 2  | music    | desc. here       |
| 3  | dance    | desc. here       |
| 4  | science  | desc. here       |
| 5  | french   | desc. here       |
| 6  | arts     | desc. here       |
+----+----------+------------------+
+-------------+------------+------------+----+
| course_id   | student_id | started    | id |
+-------------+------------+------------+----+
| 1           | 1          | false      | 1  |
| 2           | 1          | false      | 2  |
| 3           | 1          | false      | 3  |
| 1           | 2          | true       | 4  |
| 2           | 2          | true       | 5  |
| 4           | 3          | false      | 6  |
| 5           | 2          | false      | 7  |
| 5           | 1          | true       | 8  |
| 6           | 2          | false      | 9  |
+-------------+------------+------------+----+
学生课程

+----+----------+------------------+
| id | name     | description      |
+----+----------+------------------+
| 1  | english  | desc. here       |
| 2  | music    | desc. here       |
| 3  | dance    | desc. here       |
| 4  | science  | desc. here       |
| 5  | french   | desc. here       |
| 6  | arts     | desc. here       |
+----+----------+------------------+
+-------------+------------+------------+----+
| course_id   | student_id | started    | id |
+-------------+------------+------------+----+
| 1           | 1          | false      | 1  |
| 2           | 1          | false      | 2  |
| 3           | 1          | false      | 3  |
| 1           | 2          | true       | 4  |
| 2           | 2          | true       | 5  |
| 4           | 3          | false      | 6  |
| 5           | 2          | false      | 7  |
| 5           | 1          | true       | 8  |
| 6           | 2          | false      | 9  |
+-------------+------------+------------+----+

到目前为止,我可以愉快地呈现所有课程的json对象,以及每门课程的所有学生的姓名,如下所示:

render json: Course.all.to_json(:include => {:students => {:only => :name}})
我还可以轻松地呈现学生正在或即将参加的所有课程

render json: @student.courses.to_json(:include => {:students => {:only => :name}})
这也包括其他参加这些课程的学生

但假设我想呈现一个学生尚未开始的课程,以及该课程的所有其他学生(无论是否已开始该课程)[请阅读下面的更新部分,我实际上在寻找相反的东西!]

我认为最简单的方法是查询join表中的以下内容:

StudentCourse.all.where(student_id: @student.id, started: false)

+-------------+------------+------------+----+
| course_id   | student_id | started    | id |
+-------------+------------+------------+----+
| 5           | 2          | false      | 7  |
| 6           | 2          | false      | 9  |
+-------------+------------+------------+----+
但是我如何从这个结果表(关联对象)得到一个包含课程名称(和所有其他属性)并包含学生的打包好的json对象,就像我使用:
Course.all.to_json(:include=>{:students=>{:only=>:name}})

我想我在这里遗漏了一些重要关键概念的基本知识,但在这一点上,我甚至无法识别它们,非常感谢您的帮助。。。多谢各位



更新: 我刚刚意识到下面的部分是我最初想要做的。恰恰相反。在所有这些细节中,我迷失了方向。我希望我可以把它加在这里

因此,给定一个学生(我们称他为Aiden),我需要返回一个JSON对象,该对象只包含他正在学习的课程和他已经开始学习的课程,只有当这些课程中有其他尚未开始学习的学生时,它还必须包含每门课程的学生的姓名。

所以

我现在有:

aiden_started_courses = Student(1).courses.where(:student_courses => {:started => true } )
对于一个学生来说,它参加了所有在联接表“开始”列中具有“true”值的课程。(同样,在联接表中,每个学生课程记录都是“合成”唯一的,因此对于给定的学生id和课程id,只能有一个唯一的记录)

在下一个查询中,对于“aiden_started_courses”的one,我可以删除所有在“started”上有错误值的相关学生课程协会

因此,问题就出在这里:我在aiden_started_courses数组中只为一门课程获取了该数据,但是我如何才能构建一个查询,返回aiden所有已启动课程的数据呢?

可以在一行中完成吗?我知道我可能会使用Ruby枚举器循环,但我有点觉得我会在Rails编码约定级别和性能级别上打破一些模式?(又碰到了N+1问题?)


到目前为止我能做的:

[
    {
        "id": 1,
        "name": "english",
        "students": [
            {"name": "ALison"},
            {"name": "Robert"}]
    },
    {
        "id": 2,
        "name": "music",
        "description": null,
        "students": [
            {"name": "Robert"},
            {"name": "Kate"}]
    }
]
我想到了这个,我发现所有没有开始某个用户已经开始的课程的学生:

Student.includes(:student_courses).
where(:student_courses => { :started => false, :course_id => aiden.courses.where
           (:student_courses => {started: true}).ids  } ) 
或者这个:

Course.includes(:students).where(:student_courses => {:started => false, 
   :course_id => aiden.courses.where(:student_courses => {:started =>true}).ids })
它查找给定学生已开始的所有课程,如果这些课程包括尚未开始的学生

但我真正需要的是得到这样一个JSON对象:

[
    {
        "id": 1,
        "name": "english",
        "students": [
            {"name": "ALison"},
            {"name": "Robert"}]
    },
    {
        "id": 2,
        "name": "music",
        "description": null,
        "students": [
            {"name": "Robert"},
            {"name": "Kate"}]
    }
]

在那里我可以看到某个学生正在上的课程和已经开始的课程,但只有那些其他学生还没有开始的课程,以及这些学生的名字

我想可能没有办法通过一个常规的AR查询来实现这一点,所以a应该手动构建JSON吗?但我怎么能做到呢



谢谢你,我为你的长篇大论道歉。。但希望它能帮助..

利用
范围
对您有利:

class Course < ActiveRecord::Base
  # ...
  scope :not_started, -> { joins(:student_courses) \
                                      .where(student_courses: {started: false}) }

  scope :with_classmates, -> { includes(:students) } # use eager loading
end
输出:

[
    {
        "id": 1,
        "name": "english",
        "description": null,
        "students": [
            {"name": "Aiden"},
            {"name": "Alison"}]},
    {
        "id": 2,
        "name": "music",
        "description": null,
        "students": [
            {"name": "Aiden"},
            {"name": "Alison"}]},
    {
        "id": 3,
        "name": "dance",
        "description": null,
        "students": [
            {"name": "Aiden"}]}]

使用JBuilder,默认情况下它与Rails一起提供。忽略以“#”开头的行:

Jbuilder.new do|j|
#课程:[{
j、 当然可以|
#身份证:
j、 课程号
#姓名:
j、 name course.name
#学生:[{
j、 学生做|学生|
#姓名:
j、 学生姓名
结束
# }]
结束
# }]
结束
没有太多的代码。删除注释并简化某些功能,其外观如下:

student_courses = <...blah...>
json = Jbuilder.new do |j|
  j.courses student_courses do |course|
    j.(course, :id, :name)
    j.students <course.students - whatever method here>, :name
  end
end.target!
学生课程=
json=Jbuilder.new do|j|
j、 课程学生做的课程|
j、 (课程编号:id:name)
j、 学生::姓名
结束
结束,目标!

看看他们的网站,在纯Ruby DSL中生成JSON非常棒。因此,请继续使用您想要获取students/courses/studentcourses的任何ruby代码。

.to_json
附加到结尾:
StudentCourse.all.where(student\u id:@student.id,start:false)。to_json
。这并不能回答我的问题。我已经(确切地)说到这一点了。我知道添加“to_json”会呈现json。。。但我想渲染的不仅仅是这个!请仔细阅读问题的最后部分。是的,对不起。要自动填充学生/课程,您应该指定
:属于
:在相应的
ActiveRecord
上有许多属性,如下所述:这已经完成!我在第一行就这么说!“我在学生和课程之间有一种多对多的关系”。。。这意味着
有很多…:通过…
s和
在模型中属于
s。请你读一下报纸好吗
Jbuilder.new do |j|

    # courses: [{
    j.courses <student.courses - replace this with whatever variable> do |course|

      # id: <course.id>
      j.id course.id 

      # name: <course.name>
      j.name course.name

      # students: [{
      j.students <course.students - replace with whatever variable> do |student|

          # name: <student.name>
          j.name student.name

      end
      # }]

   end
   # }]

end
student_courses = <...blah...>
json = Jbuilder.new do |j|
  j.courses student_courses do |course|
    j.(course, :id, :name)
    j.students <course.students - whatever method here>, :name
  end
end.target!