2017-10-21 99 views
0

我想了解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 

但軌道控制檯提供了以下錯誤:

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: 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:M招生M:1個M部分:1場

或學生L:M截面。註冊是學生與科之間M:M關係的加入表,不是?

所以馬上我們看到,學生應該是:

rails g student name 
class Student < ApplicationRecord 
    has_many :enrollments 
    has_many :sections, through: :enrollments 
end 

擴招是一個連接表,所以它需要的學生和部分的IDS

rails g enrollment student_id section_id 
class Enrollment < ApplicationRecord 
    belongs_to :student 
    belongs_to :section 
end 

(定義屬於只如果你想工作一個註冊實例並與它的關係一起工作,則是必要的)

該部分

rails g section name course_id 
class Section < ApplicationRecord 
    has_many :enrollments 
    has_many :students, through: :enrollments 
    belongs_to :course 
end 

而且當然

rails g course name 
class Course < ApplicationRecord 
    has_many :sections 
end 

,並把這個在一起的時候,我們要一起工作(同樣,has_manys如果你想獲得就讀於部分學生只需要)學生的一個實例(獲得一個特定學生的所有課程註冊),因此self.courses_enrolled_in(student_id)聲明是錯誤的方法。你應該可以嘗試出這一切在軌道控制檯,所以你會通過讓學生開始:

[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爲您做好工作,那就是它的存在。你提供的關係定義是你如何指定你想要的連接。

1

在where函數中指定連接的條件時,應該指定表名稱而不是關聯名稱。所以你的例子可能需要使用「註冊」。 Active Record Query Interface Rails指南應該可以幫助您理解使用Active Record進行查詢