2017-12-18 21 views
1

내 목표는 Member 개체의 모든 완료 과정을 볼 수있는 범위를 만드는 것입니다.복잡한 레일 has_many 범위에서 외부 조인을 만들 수 있습니까?

Course은 많은 Sections으로 구성됩니다. Section 당 하나의 Quiz이 있습니다. Course을 완료하려면 모든 Quizcomplete으로 설정해야합니다. 예를 들어

는 :

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

이 범위의 이런 종류의 작성에 최선을 시도한다 : 내가 부족

# 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 

부분은 실제로 SQL하지 않습니다이 부분 count(sections.quizzes.id)입니다 . 나는 이것이 어떤 종류의 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이있다 : 각 섹션 quizz을 완료하면,이 경우에는 having

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 

조건 cources.id 각 그룹을 필터링한다.

+0

이것은 정말 놀라운 일입니다. 감사합니다. 모든 퀴즈가 완료 되더라도 항상 [] 값을 반환하기 때문에 정확하게 작동하지 않습니다. 위의 예제를 통해 업데이트 할 것입니다. – Trip

+1

Woops, 그냥 다 알아 냈어. (내가 말하지 않은 다른 속성과 관련이있다.) 도와 주셔서 정말 감사합니다! 너 내가이 문제를 해결하는 걸 도왔다. 정말 고마워! – Trip