Rails 3.1 - 使用范围查找未注册的学生

Amm*_*mar 1 scope nested associations ruby-on-rails-3.1

# student.rb
has_and_belongs_to_many :courses

# course.rb
has_and_belongs_to_many :students
Run Code Online (Sandbox Code Playgroud)

我正在尝试在学生模型中创建一个范围,以检查他们是否注册了课程.

我提出的最好的是:

scope :unenrolled, where(Student.courses.count => 0)
Run Code Online (Sandbox Code Playgroud)

但后来我得到了错误信息

未定义的方法`课程'

有人提出任何建议吗?

Jor*_*ing 5

好吧那么.所以这是你的代码:

scope :unenrolled, where(Student.courses.count => 0)
Run Code Online (Sandbox Code Playgroud)

这里的第一个问题是导致错误的事情:你在上调用实例方法.顾名思义,您只能在类的实例上调用实例方法,而不能在类本身上调用.例如:courses Student

jim = Student.find(123)
jims_courses = jim.courses
Run Code Online (Sandbox Code Playgroud)

但这里是踢球者:当你scope上下文中调用时,即代码不在实例方法中,因此在首次声明模型时会调用它.当时没有实例,所以你不能courses像在一个Student实例方法中那样调用.

但这有点没有实际意义,因为你有点误解了它是如何where运作的.您给出的参数where应该是与您在SQL查询中放置的内容相对应的条件WHERE.例如where(:eye_color => 'brown')将变成一个WHERE类似的SQL 子句WHERE eye_color = 'brown'.:eye_color => 'brown'只是一个带有键值的哈希:eye_color'brown'.=>除非函数返回模型中ActiveRecord将理解的列/属性的名称,否则调用左侧的函数没有意义.

现在让我们弄清楚你应该做些什么.如果您正在编写SQL查询,它将看起来像这样:

SELECT `students`.*, COUNT(`courses_students`.*) AS `courses_count`
  FROM `students`
  JOIN `courses_students` ON `students`.`id` = `courses_students`.`student_id`
 WHERE `courses_count` = '0'
 GROUP BY `courses_students`.`student_id`;
Run Code Online (Sandbox Code Playgroud)

这大致转换为ActiveRecord查询,如下所示:Student.joins(:courses).// AR courses通过courses_students select('students.,COUNT(courses.)AS courses_count')自动加入.where('courses_count = 0').组( 'ID')

你可以将它直接插入你的范围:

scope :unenrolled,  joins(:courses).
                    select('students.*, COUNT(courses.*) AS courses_count').
                    where('courses_count = 0').
                    group('courses.course_id')
Run Code Online (Sandbox Code Playgroud)

注意:这些查询有点偏僻,可能需要稍微调整一下.构建复杂的ActiveRecord查询的最简单方法是将它们直接输入Rails控制台,直到获得所需的结果.

希望有用!