具有多个联接的ActiveRecord查询无法识别关系

我正在尝试编写一个ActiveRecord查询,该查询使用以下查询返回在特定课程中注册的所有学生:

def self.students_enrolled_in(course_id) Student .joins(:enrollments) .joins(:sections) .joins(:courses) .where(sections: { course_id: course_id }) end 

rails控制台的结果是:

ActiveRecord :: ConfigurationError:无法将’Student’加入名为’sections’的关联; 也许你拼错了吗?

这似乎是关联的结果。 我究竟做错了什么? 查询实际上是否意味着所有join()语句都必须与Student关联,或者是否应该跟踪关联链接?

教授节目页面:

 

Card image cap

楷模:

注册

 class Enrollment < ApplicationRecord belongs_to :section belongs_to :student end 

学生:

 class Student < ApplicationRecord has_many :enrollments end 

教授:

 class Section (prof_id) { where('professor_id = ?', prof_id) } end 

课程:

 class Course  { where(status: 1) } scope :planning, -> { where(status: 0) } belongs_to :department has_many :sections has_many :professors, through: :sections validates :title, :number, :status, :description, presence: true validates :description, length: { in: 10..500 } validates :title, :number, uniqueness: { case_sensitive: false } def self.search(term) if term where('title LIKE ?', "%#{term}%").order('title DESC') else order('title ASC') end end def self.taught_by(professor_id) Course .joins(:sections) .joins(:professors) .where(sections: { professor_id: professor_id }) .select('distinct courses.*') end end 

架构:

 ActiveRecord::Schema.define(version: 20171013201907) do create_table "courses", force: :cascade do |t| t.string "title" t.text "description" t.string "number" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "status", default: 0 t.integer "department_id" t.index ["department_id"], name: "index_courses_on_department_id" end create_table "departments", force: :cascade do |t| t.string "name" t.text "description" t.text "main_image" t.text "thumb_image" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "enrollments", force: :cascade do |t| t.integer "section_id" t.integer "student_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["section_id"], name: "index_enrollments_on_section_id" t.index ["student_id"], name: "index_enrollments_on_student_id" end create_table "professors", force: :cascade do |t| t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "status", default: 0 t.integer "department_id" t.text "bio" t.index ["department_id"], name: "index_professors_on_department_id" end create_table "sections", force: :cascade do |t| t.integer "number" t.integer "max_enrollment" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "professor_id" t.integer "course_id" t.string "room" t.index ["course_id"], name: "index_sections_on_course_id" t.index ["professor_id", "course_id"], name: "index_sections_on_professor_id_and_course_id", unique: true t.index ["professor_id"], name: "index_sections_on_professor_id" end create_table "students", force: :cascade do |t| t.string "name" t.decimal "gpa" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "name" t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" t.integer "sign_in_count", default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" t.string "current_sign_in_ip" t.string "last_sign_in_ip" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "roles" t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end end 

你过度申请了.joins 。 尝试从内到外开始。 首先,找到课程:

 Course.find_by(id: course_id) 

然后,找到与course相关的所有部分。 这里不需要joins

 Section.where(course: Course.find_by(id: course_id)) 

现在你加入:

 Student.joins(:enrollments).where(enrollments: {section: Section.where(course: Course.find_by(id: course_id))}) 

认为应该为你做的伎俩。 但是,未经测试。 所以,试一试,看看它是否有效。

PS:尝试仅发布最相关的代码。 排序一堆无关紧要的东西并不是那么有趣。

另一种方法是在Student模型中添加更多关联:

 class Student < ApplicationRecord has_many :enrollments has_many :sections, through: :enrollments has_many :courses, through: :sections scope :enrolled_in_course, -> (course) { joins(:sections).where(course_id: course.id) end 

然后,您可以找到所有注册course学生:

 Student.enrolled_in_course(course) 

朋友。

学生.joins(注册:[:sections,:courses])。where(sections:{course_id:course_id})

要么

学生.joins(注册:[:sections])。where(sections:{course_id:course_id})