【问题标题】:How to write a Rails SQL query for finding an object where all children have an equal value如何编写 Rails SQL 查询以查找所有子对象具有相同值的对象
【发布时间】:2017-10-24 10:06:32
【问题描述】:

我一直在阅读这篇文章,但无法将其写入 Rails 范围:

find all parent records where all child records have a given value (but not just some child records)

我有一个 CourseSectionQuiz 对象:

class Course < ActiveRecord::Base
  has_many :course_members
  has_many :members, through: :course_members
  has_many :sections
  has_many :quizzes, through: :sections
end

class Quiz < ActiveRecord::Base
  belongs_to :member
  belongs_to :section
end

class Section < ActiveRecord::Base
  belongs_to :course
  has_many :quizzes
end

我想查找会员的所有课程,其中与该课程相关的所有测验都具有completed = true 属性。

所以在我的Member 课程中,我最好写一些类似的东西:

has_many :completed_courses, -> { 
   joins(:courses, :quizzes, :sections)
   # .select( 'CASE WHEN quizzes.completed = true then 1 end') ??? maybe ???
}, class_name: 'Course'

哈哈!但除非这太复杂了。我一直在尝试把这个简单地写在Course 中也可以。

【问题讨论】:

  • 为什么是relational-algebra

标签: sql ruby-on-rails postgresql activerecord relational-algebra


【解决方案1】:
class Member < ActiveRecord::Base
  has_many :courses, through: :course_members
  has_many :course_members

  has_many :completed_courses,
    -> { joins(:quizzes).where.not(quizzes: {completed: [false, nil]}) },
    through: :course_members,
    source: :course
end

如果您的 completed 布尔列是 NOT NULL,则将上面的 [false, nil] 更改为简单的 false

使用示例

irb(main):002:0> Member.first.completed_courses
  Member Load (0.2ms)  SELECT "members".* FROM "members" ORDER BY "members"."id" ASC LIMIT 1
  Course Load (0.1ms)  SELECT "courses".* FROM "courses" INNER JOIN "sections" ON "sections"."course_id" = "courses"."id" INNER JOIN "quizzes" ON "quizzes"."section_id" = "sections"."id" INNER JOIN "course_members" ON "courses"."id" = "course_members"."course_id" WHERE (NOT (("quizzes"."completed" = 'f' OR "quizzes"."completed" IS NULL))) AND "course_members"."member_id" = ?  [["member_id", 1]]

【讨论】:

  • 这看起来完全正确。非常感谢。我遇到了最奇怪的错误:D, [2017-10-24T13:41:08.364579 #5326] DEBUG -- : Member Load (1.6ms) SELECT "members".* FROM "members" ORDER BY "members"."id" ASC LIMIT 1 NoMethodError: undefined method name' for nil:NilClass .. 但没有任何东西有 name 属性..
  • 没有问题! :) 不确定为什么要调用 :members 关联。你在某处有default_scope 吗?你可以试试这个吗? has_many :completed_courses, -&gt; { unscoped.joins(:quizzes).where.not(quizzes: {completed: [false, nil]}) }, class_name: 'Course'
  • 我是通过 Member 类来调用它的。你打算把这个电话放在哪里?
  • 是的,我假设您在 Member 类中调用它。就像Member.first.completed_courses。但是我说的:membersCourse has_many :members,以防你的Course 类有default_scope。它奏效了吗?如果没有,你能提供完整的堆栈跟踪吗?
  • 啊它确实有一个默认范围..哈..那个老错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多