那么看起来您要问的是,鉴于学生注册了许多课程的许多部分,该学生注册了哪些课程?
我们将忽略教授,因为这与原始问题无关。
或者换一种说法
学生 1:M 注册 M:1 部分 M:1 课程
或学生 M:M 部分。 Enrollments 是 Student 和 Section 之间 M:M 关系的联接表,不是吗?
所以我们马上看到学生应该是:
rails g student name
class Student < ApplicationRecord
has_many :enrollments
has_many :sections, through: :enrollments
end
Enrollments 是一个连接表,所以它需要学生和部门的 ID
rails g enrollment student_id section_id
class Enrollment < ApplicationRecord
belongs_to :student
belongs_to :section
end
(仅当您想要使用 Enrollment 实例并使用它的关系时才需要定义所属)
部分
rails g section name course_id
class Section < ApplicationRecord
has_many :enrollments
has_many :students, through: :enrollments
belongs_to :course
end
(同样,has_manys 仅在您想让学生注册某个部分时才需要)
还有课程
rails g course name
class Course < ApplicationRecord
has_many :sections
end
当把它放在一起时,我们想要使用 Student 的实例(获取特定学生注册的所有课程),因此 self.courses_enrolled_in(student_id) 语句是错误的处理方式。您应该可以在 Rails 控制台中尝试这一切,因此您可以从获取学生开始:
(为简洁起见,从控制台输出中省略了时间戳)
[9] pry(main)> student = Student.first
Student Load (13.8ms) SELECT `students`.* FROM `students` ORDER BY `students`.`id` ASC LIMIT 1
=> #<Student:0x007fc40fb88b68
id: 1,
name: "Fred",
现在我们有了学生,问它有哪些部分:
pry(main)> sections = student.sections
Section Load (14.1ms) SELECT `sections`.* FROM `sections` INNER JOIN `enrollments` ON `sections`.`id` = `enrollments`.`section_id` WHERE `enrollments`.`student_id` = '1'
=> [#<Section:0x007fc40c474208
id: 1,
name: "1st period",
course_id: "1",
#<Section:0x007fc40c474028
id: 5,
name: "2nd period",
course_id: "2",
#<Section:0x007fc40c46fe60
id: 9,
name: "3rd period",
course_id: "3",
]
对于每个部分,我们都可以获得课程:
pry(main)> sections.first.course
Course Load (17.1ms) SELECT `courses`.* FROM `courses` WHERE `courses`.`id` = 1 LIMIT 1
=> #<Course:0x007fc40f756a18
id: 1,
name: "English",
这将为集合中的每个结果运行单独的查询,而不是最佳的,因此我们可以使用包含进行急切加载:
pry(main)> student.sections.includes(:course)
Section Load (5.9ms) SELECT `sections`.* FROM `sections` INNER JOIN `enrollments` ON `sections`.`id` = `enrollments`.`section_id` WHERE `enrollments`.`student_id` = '1'
Course Load (9.5ms) SELECT `courses`.* FROM `courses` WHERE `courses`.`id` IN (1, 2, 3)
=> [#<Section:0x007fc40faa13a8
id: 1,
name: "1st period",
course_id: "1",
#<Section:0x007fc40faa11c8
id: 5,
name: "2nd period",
course_id: "2",
#<Section:0x007fc40faa0fe8
id: 9,
name: "3rd period",
course_id: "3",
那么现在:
pry(main)> sections.first.course
=> #<Course:0x007fc40f6cc570
id: 1,
name: "English",
没有额外的查询。为了简化事情,我会在注册表中添加一个 course_id 字段,然后添加:
rails g student name
class Student < ApplicationRecord
has_many :enrollments
has_many :sections, through: :enrollments
has_many :courses, through: :enrollments
end
总之,关于join是怎么做的?让 ActiveRecord 为您完成工作,这就是它的用途。您提供的那些关系定义就是您指定所需连接的方式。