2017-12-18 9 views
1

私の目標は、Memberオブジェクトの完成したすべてのコースを見ることができる範囲を作ることです。複雑なRails has_manyスコープで外部結合を作成するにはどうすればよいですか?

Courseは多くのSectionsで構成されています。 SectionにはQuizが1つあります。 Courseが完了するためには、すべてのQuizcompleteに設定する必要があります。例えば

:私は欠けている部分が実際にSQLではありませんこの部分count(sections.quizzes.id)ある

# Member.rb 

has_many :completed_courses, -> { 
    joins(:quizzes, :sections) 
    .where(quizzes: {completed: true}) 
    .group('members.id HAVING count(sections.quizzes.id) = count(sections.id)') 
}, through: :course_members, source: :course 

Course 
    Section A -> Quiz A (Complete) 
    Section B -> Quiz B (Complete) 
    Section C -> Quiz C (Complete) 

これはスコープのこの種の書き込みで私の最高の試みであります。どのような種類のJOINが呼び出されるのかは完全にはわかりませんが、countのコースに所属する完成したクイズをいくつかのセクションと比較する必要があります。それらが等しい場合、それはすべてのクイズが完了したことを意味します。

このようなJOINの名前を知っているだけで、私は正しい方向に向かうでしょう。


更新

私はの応答@jamesdevar使用してみました:

has_many :completed_courses, -> { 
    joins(:sections) 
    .joins('LEFT JOIN quizzes ON quizzes.section_id = sections.id') 
    .having('COUNT(sections.id) = SUM(CASE WHEN quizzes.completed = true THEN 1 ELSE 0 END)') 
    .group('courses.id') 
}, through: :course_members, source: :course 

をしかし、とき、それはいけない、それは[ ]値を返します。たとえば、私はこのデータを持っています:

-> Course{id: 1} 
    -> Section{id: 1, course_id: 1} 
     -> Quiz{section_id: 1, member_id: 1, completed: true} 

コースは合計で1セクションです。セクションには、他のメンバーから数百のクイズが関連付けられている場合がありますが、この特定のメンバーのクイズは完了しています。

私は、このSQLの比較が個々のメンバーに固有のものではないと考えています。

.having('COUNT(sections.id) = SUM(CASE WHEN quizzes.completed = true THEN 1 ELSE 0 END)') 

生成される実際のSQLはこれです:各セクションは、クイズを完了したときhaving条件によって各cources.idグループをフィルタリングします。この場合

SELECT "courses".* FROM "courses" 
INNER JOIN "sections" ON "sections"."course_id" = "courses"."id" 
INNER JOIN "course_members" ON "courses"."id" = "course_members"."course_id" 
LEFT JOIN quizzes ON quizzes.section_id = sections.id 
WHERE "course_members"."member_id" = $1 
GROUP BY courses.id 
HAVING COUNT(sections.id) = SUM(CASE WHEN quizzes.completed = true THEN 1 ELSE 0 END) 
ORDER BY "courses"."title" 
ASC [["member_id", 1121230]] 

答えて

1
has_many :completed_courses, -> { 
    joins(:sections) 
    .joins('LEFT JOIN quizzes ON quizzes.section_id = sections.id') 
    .having('COUNT(sections.id) = SUM(CASE WHEN quizzes.completed = true THEN 1 ELSE 0 END)') 
    .group('courses.id') 
}, through: :course_members, source: :course 

+0

これは本当に素晴らしいです、ありがとうございます。すべてのクイズが完了しても常に[]を返すので正確には機能しません。上記で例を挙げて更新します。 – Trip

+1

Woopsは、すべてのことを考え出しました(これは、私があなたに話していなかった他の属性と関連していました)。手伝ってくれてどうもありがとう!あなたは私を完全に解決するのを助けました。本当にありがとう! – Trip

関連する問題