我正在尝试了解ActiveRecord查询。来自sql背景,它有点令人困惑。我正在尝试编写一个查询,以便通过以下查询获取特定学生注册的所有课程:
def self.courses_enrolled_in(student_id)
Course.joins(:sections).where(sections: {enrollment: Enrollment.where(student: Student.find_by(id: student_id))})
end
但rails控制台出现以下错误:
ActiveRecord :: StatementInvalid:SQLite3 :: SQLException:没有这样的列:sections.enrollment:
这是从之前的asked question拼凑而成的,由内而外。我理解错误在说什么,但我想我还不清楚如何将连接链接在一起,就像在sql中将一个表连接到另一个表。如何编写查询以拉出特定学生注册的所有课程?
模型:
注册
class Enrollment < ApplicationRecord
belongs_to :section
belongs_to :student
end
学生:
class Student < ApplicationRecord
has_many :enrollments
end
教授:
class Section < ApplicationRecord
has_many :enrollments
belongs_to :professor
belongs_to :course
end
课程:
class Course < ApplicationRecord
belongs_to :department
has_many :sections
has_many :professors, through: :sections
end
答案 0 :(得分:1)
在where函数中指定连接的条件时,应指定表名而不是关联名。因此,您的示例可能需要使用“注册”。 Active Record Query Interface Rails指南应该帮助您理解使用Active Record查询
答案 1 :(得分:0)
所以你问的是,考虑到学生参加了许多课程的许多部分,哪些课程是学生注册的?
我们会忽略教授,因为这与原始问题无关。
或换句话说
学生1:M注册M:1节M:1课程
或学生M:M部分。注册是学生和科之间M:M关系的连接表,没有?
我们马上就看到学生应该:
rails g student name
class Student < ApplicationRecord
has_many :enrollments
has_many :sections, through: :enrollments
end
注册是一个连接表,因此它需要学生和部分的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
总之,关于如何进行加入?让ActiveRecord为您完成工作,这就是它的用途。您提供的关系定义是指定所需联接的方式。