我对 Rails 还很陌生,我正在尝试为一所学校制作一个数据库应用程序作为练习。所以这是我构建的 ERD:
我想要的是一个学校下的学生名单。我知道如何检索学校下的老师和老师下的学生,基本上只是 school.teachers
和 teacher.students
,但我不知道如何获取学校 -> 学生。
答案 0 :(得分:3)
你可以设置一个has many through关系:
class Teacher < ApplicationRecord
belongs_to :school
has_many :students
end
class School < ApplicationRecord
has_many :teachers
has_many :students, through: :teachers
end
然后就去做
school = School.find(some_id)
students = school.students
一些注意事项:
Rails 中的外键通常采用 something_id
格式,因此您可以使用 TeacherId
代替 teacher_id
。主键通常仅称为 id
。当然,您可以随意调用它们,如果您使用默认值,则只需较少的配置即可。
除非这只是为了玩 Rails,否则我可能会将老师和学生之间的关系更改为多对多。在这种情况下,您需要distinct
学生:
has_many :students, -> { distinct }, through: :teachers
更新:
多对多
是的,你说得对。要拥有多对多关系,您将需要一个“连接表”。不过,这不是 Rails 强制要求的,而是关系数据库的工作方式。如果您在走这条路线方面需要帮助,最好提出一个新问题。
通过
:through
是一个可以传递给 has_many
的选项。它描述here
https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association(虽然他们在示例中使用了“has and属于 many”关联)
在你的例子中,我认为它是这样的:“嘿,学校,请给我你可以通过老师联系到的所有学生”
ActiveRecord 将创建一个类似于此的查询:
school = School.first
school.students.to_sql
=> "SELECT \"students\".* FROM \"students\" INNER JOIN \"teachers\" ON \"students\".\"teacher_id\" = \"teachers\".\"id\" WHERE \"teachers\".\"school_id\" = 1"
(其中 1
是您调用 students
方法的学校的 ID)。
如果你按照@TTD 的建议进行查询,那么它很可能会导致这样的结果:
school = School.first
Student.where(teacher: Teacher.where(school: s)).to_sql
=> "SELECT \"students\".* FROM \"students\" WHERE \"students\".\"teacher_id\" IN (SELECT \"teachers\".\"id\" FROM \"teachers\" WHERE \"teachers\".\"school_id\" = 1)"
同样有效,但使用嵌套查询来获取教师 ID。
还有另一种我不时使用的方法:
school = School.first
teacher_ids = school.teachers.pluck(:id) # only select the teacher ids
students = Student.where(teacher_id: teacher_ids)
不过我不建议这样做。它将触发两个查询以获取学生并来回传输更多数据:
答案 1 :(得分:1)
Student.where(teacher: Teacher.where(school: school))