渲染的连接模型的JSON对象及其关联模型 [英] Rendering a JSON object of a join-model and its associated models

查看:212
本文介绍了渲染的连接模型的JSON对象及其关联模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一个Rails(4.1.5 /红宝石2.0.0p481 / Win64上)应用程序,我之间有很多一对多的关系的学生课程的和一个联接模型 StudentCourse 的其中重presents的关联,并具有附加属性所谓的开始的(默认的假设置)。

In a Rails ( 4.1.5 / ruby 2.0.0p481 / win64 ) application I have a many-to-many relationship between Student and Course and a join model StudentCourse which represents the association, and has an additional attribute called started (set by default on "false").

我也有在连接表制成的 STUDENT_ID 的补充索引和的 COURSE_ID 的,并设置了一个独特的检查,像这样

I also have added an index in the join-table made of student_id and course_id, and set a unique check on that, like this

t.index [:student_id, :course_id], :unique => true, :name => 'by_student_and_course'

我想这是个复合主键,但由于在轨没有复合主键(不要使用宝石)我还添加了一个主键名为id:

I wanted that to be a composite primary key, but since in rails there are no composite primary keys (without using a gem) I also added a primary key called id:

t.column :id, :primary_key

现在我看到,协会是由要么做创建:

Now I see that associations are created by either doing:

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

Course.first.students << Student.first

这是罚款,这是预期的行为,我想。

This is fine and it's the expected behaviour, I suppose.


话虽如此,我挣扎环绕在ActiveRecord的查询关联的决议我的脑海里。让我来解释这更好的:


That said, I am struggling to wrap my mind around association resolutions in ActiveRecord queries. Let me explain this better:

有关参考, Student.all Course.all StudentCourses.all 将返回这样的表:

For reference, Student.all, Course.all and StudentCourses.all would return tables like these:

Student.all

Student.all

+----+-----------+
| id | name      |
+----+-----------+
| 1  | Aidan     |
| 2  | Alison    |
| 3  | Elizabeth |
+----+-----------+

Course.all

Course.all

+----+----------+------------------+
| 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       |
+----+----------+------------------+

StudentCourse.all

StudentCourse.all

+-------------+------------+------------+----+
| 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对象,并且所有学生每门课程像这样的名字:

So far I can happily render a json object of all courses, and names of all students for each course like this:

render json: Course.all.to_json(:include => {:students => {:only => :name}})

我也可以很容易地使一个学生参加所有课程或即将参加与

I can also easily render all courses that a student is attending or about to attend with

render json: @student.courses.to_json(:include => {:students => {:only => :name}})

其中还包括其他学生的课程。

which also includes other students for those courses.

但是假设我想使学生尚未开始哪一个学生的课程,以及所有其他学生谁在该课程(有或没有启动的过程中) [请阅读下面的更新部分,我在寻找相反的事居然!]

But suppose I wanted to render one student's courses which the student has not yet started, together with all the other students who are on that course (which have or not started the course) [Please read the UPDATE section below, I'm looking for the opposite thing actually!]

我觉得easieast方法是查询加盟 - 表是这样的:

I think the easieast approach is to query the join-table for something like:

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(:包括=&GT; {:学生=&GT; {:只=&GT;:名}})?

But how do I go on from this resulting table (association object) to get a nicely packaged json object with courses names (and all other attributes) and also including students in it, like I did with: Course.all.to_json(:include => {:students => {:only => :name}}) ?

我觉得我失去了一些重要的关键概念的一些基本知识,在这里,但在这一点上,我甚至不能indentify他们,将大大AP preciate一些帮助......谢谢你。

I think I'm missing some basic knowledge of some important key concepts here, but at this point I cannot even indentify them and would greatly appreciate some help... thank you.





我刚刚意识到,下面的部分是什么,我本来试图做的。这是相反的事。在所有这些细节,我得到了沿途丢失。我希望这是确定,如果我只是在这里添加。

I just realized that the following part is what I was originally trying to do. It's the opposite thing. Among all these details I got lost along the path. I hope that it's ok if I just add it here.

所以,对于一个学生(让我们叫他艾登),我需要返回只包含自己是在和的他已经开始了课程只是一个JSON对象的时,这些课程已经在他们的其他同学谁的还没有开始他们的的,并且它必须包括学生每门课程的名称了。

So, given a student (let's call him Aiden), I need to return a JSON object containing only the courses that he is in and that he has started, only when such courses have other students in them who have not started them, and it has to include the names of those students for each course too.

所以...

我现在有:

aiden_started_courses = Student(1).courses.where(:student_courses => {:started => true } )

这对于一个的学生的通吃的课程的已在连接表真值启动栏。 (再次在连接表中的每个的学生课程的记录是复合地唯一的,因此可以只为一个唯一的记录对于给定的STUDENT_ID和COURSE_ID)。

which for a student takes all the courses that have a "true" value in the join-table "started" column. (again in the join table each student-course record is "compositely" unique, so there can just be one unique record for a given student_id and course_id).

随着下一个查询,为一个aiden_started_courses我可以拉了所有的相关的学生的课程的关联这对开始假值

With the next query, for one of "aiden_started_courses" I can pull off all the relative student-courses associations which have a false value on "started"

aiden_started_courses[0].student_courses.where(:started => false).includes(:student).to_json(:include => :student)

+-------------+------------+------------+----+
| course_id   | student_id | started    | id |
+-------------+------------+------------+----+
| 1           | 2          | false      | 4  |
+-------------+------------+------------+----+
| 1           | 9          | false      | 5  |
+-------------+------------+------------+----+

因此​​,这里存在一个问题:我设法得到这只是在一个单一的过程中的 aiden_started_courses 的数组,但我将如何能够建立返回该数据的查询艾登的所有的开始课程?

So here lies the problem: I have managed to get this just for a single course in aiden_started_courses array, but how would I be able to build a query that returns this data for all of Aiden's started courses?

是否有可能做到这一点在同一行?我知道我大概可以使用Ruby枚举循环,但我有点觉得有种,我会打破一些模式上都Rails的编码约定水平和性能水平? (再次创下N + 1问题?)...

Is it possible to do that in one line? I know I could probably use Ruby enumerator loops but I somewhat feel that I would be kind of breaking some pattern both on a Rails coding convention level and on performance level? (hitting N+1 problem again?) ...


我能到目前为止:

我想出了这个,我觉得谁还没开始给定的用户已经开始该课程所有学生:

I came up with this where I find all students who have not started the courses which a given user has started:

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

或者这样的:

or this:

Course.includes(:students).where(:student_courses => {:started => false, 
   :course_id => aiden.courses.where(:student_courses => {:started =>true}).ids })

这将找到所有给定的学生已经开始,如果这些课程包括:谁还没开始他们还没有学生课程

which finds all the courses that a given student has started if those courses include students who have not started them yet

但我真正需要的是让这样的JSON对象:

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


在那里我可以看到一个给定的学生,并已经开始,但只有那些在其中也有其他同学尚未启动它的课程,再加上这些学生的名字......


where I can see the courses that a given student is on and has started, but only those in which there are other students that have not yet started it, together with the names of those students...

我手动想,大概是没有办法,我怎么能得到通过常规AR查询,所以也许应该构建一个JSON?但是,我怎么能做到这一点?

I'm thinking that probably there is no way how I could get that through a regular AR query, so maybe should a build a JSON manually? But how could I do that?


由于在副词。我的冗长表示歉意..但希望这将帮助..


Thanks in adv. and I apologise for the verbosity.. but hopefully it will help..

推荐答案

使用JBuilder中,谈到在默认情况下使用Rails。忽略以'#'的行:

Use JBuilder, it comes by default with Rails. Ignore the lines starting with '#':

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

不是很多code。删除评论和简化一些功能,它看起来像:

Not a lot of code. Removing the comments and simplifying some features, it will look like:

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!

看看他们指南,其pretty的真棒生成JSON纯Ruby的DSL。所以,尽管无论红宝石code要提取学生/场/ studentcourses使用。

Check out their guide, its pretty awesome to generate JSON in plain Ruby DSL. So go ahead and use whatever ruby code you want to fetch students/courses/studentcourses.

这篇关于渲染的连接模型的JSON对象及其关联模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆