From 07b7561b55d9e6455f8525ea522b192ef757c87f Mon Sep 17 00:00:00 2001 From: Alex Basson Date: Thu, 21 Oct 2021 21:30:34 -0400 Subject: [PATCH] Move score computation into SurveyItemResponse --- app/controllers/dashboard_controller.rb | 19 +------ app/models/survey_item_response.rb | 18 +++++- .../features/school_dashboard_feature_spec.rb | 24 +++++--- spec/models/survey_item_response_spec.rb | 55 +++++++++++-------- 4 files changed, 65 insertions(+), 51 deletions(-) diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 68fad040..ade6f53d 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -15,7 +15,6 @@ class DashboardController < SqmApplicationController end - private def measure_ids @@ -23,22 +22,8 @@ class DashboardController < SqmApplicationController end def presenter_for_measure(measure) - score = sufficient_data?(measure: measure) ? score(measure: measure) : nil - - MeasureGraphRowPresenter.new( - measure: measure, - score: score - ) - end + score = SurveyItemResponse.score(measure: measure, school: school, academic_year: academic_year) - def sufficient_data?(measure:) - SurveyItemResponse.sufficient_data?(measure: measure, academic_year: academic_year, school: school) + MeasureGraphRowPresenter.new(measure: measure, score: score) end - - def score(measure:) - SurveyItemResponse.for_measure(measure) - .where(academic_year: academic_year, school: school) - .average(:likert_score) - end - end diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index a3f85216..630b5255 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -8,17 +8,29 @@ class SurveyItemResponse < ActiveRecord::Base scope :for_measures, ->(measures) { joins(:survey_item).where('survey_items.measure_id': measures.map(&:id)) } scope :for_measure, ->(measure) { joins(:survey_item).where('survey_items.measure_id': measure.id) } + scope :for_teacher_responses_for_measure, ->(measure) { for_measure(measure).where("survey_items.survey_item_id LIKE 't-%'") } + scope :for_student_responses_for_measure, ->(measure) { for_measure(measure).where("survey_items.survey_item_id LIKE 's-%'") } - def self.sufficient_data?(measure:, academic_year:, school:) + def self.score(measure:, school:, academic_year:) + return nil unless SurveyItemResponse.sufficient_data?(measure: measure, school: school, academic_year: academic_year) + + SurveyItemResponse.for_measure(measure) + .where(academic_year: academic_year, school: school) + .average(:likert_score) + end + + private + + def self.sufficient_data?(measure:, school:, academic_year:) meets_teacher_threshold = true meets_student_threshold = true if measure.includes_teacher_survey_items? - meets_teacher_threshold = SurveyItemResponse.for_measure(measure).where("survey_items.survey_item_id LIKE 't-%'").where(academic_year: academic_year, school: school).count >= TEACHER_RESPONSE_THRESHOLD + meets_teacher_threshold = SurveyItemResponse.for_teacher_responses_for_measure(measure).where(academic_year: academic_year, school: school).count >= TEACHER_RESPONSE_THRESHOLD end if measure.includes_student_survey_items? - meets_student_threshold = SurveyItemResponse.for_measure(measure).where("survey_items.survey_item_id LIKE 's-%'").where(academic_year: academic_year, school: school).count >= STUDENT_RESPONSE_THRESHOLD + meets_student_threshold = SurveyItemResponse.for_student_responses_for_measure(measure).where(academic_year: academic_year, school: school).count >= STUDENT_RESPONSE_THRESHOLD end meets_teacher_threshold and meets_student_threshold diff --git a/spec/features/school_dashboard_feature_spec.rb b/spec/features/school_dashboard_feature_spec.rb index c382bdb3..53c68636 100644 --- a/spec/features/school_dashboard_feature_spec.rb +++ b/spec/features/school_dashboard_feature_spec.rb @@ -30,23 +30,31 @@ feature 'School dashboard', type: feature do before :each do survey_items_for_measure_1A_i.each do |survey_item| - SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, - survey_item: survey_item, likert_score: 4 + 200.times do + SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, + survey_item: survey_item, likert_score: 4 + end end survey_items_for_measure_2A_i.each do |survey_item| - SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, - survey_item: survey_item, likert_score: 5 + 200.times do + SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, + survey_item: survey_item, likert_score: 5 + end end survey_items_for_measure_4C_i.each do |survey_item| - SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, - survey_item: survey_item, likert_score: 1 + 200.times do + SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, + survey_item: survey_item, likert_score: 1 + end end survey_items_for_subcategory.each do |survey_item| - SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, - survey_item: survey_item, likert_score: 4 + 200.times do + SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, + survey_item: survey_item, likert_score: 4 + end end end diff --git a/spec/models/survey_item_response_spec.rb b/spec/models/survey_item_response_spec.rb index a9e898ae..3616c7b4 100644 --- a/spec/models/survey_item_response_spec.rb +++ b/spec/models/survey_item_response_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe SurveyItemResponse, type: :model do - describe '.sufficient_data?' do let(:measure) { create(:measure) } let(:school) { create(:school) } @@ -9,16 +8,22 @@ describe SurveyItemResponse, type: :model do context 'when the measure includes only teacher data' do let(:teacher_survey_item_1) { create(:survey_item, survey_item_id: 't-question-1', measure: measure) } + let(:teacher_survey_item_2) { create(:survey_item, survey_item_id: 't-question-2', measure: measure) } + let(:teacher_survey_item_3) { create(:survey_item, survey_item_id: 't-question-3', measure: measure) } context 'and there is sufficient teacher data' do before :each do - SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD.times do - create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school) + 4.times do + create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 3) + create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 5) + create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 3) + create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 5) end + create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 4) end - it 'is truthy' do - expect(SurveyItemResponse.sufficient_data?(measure: measure, academic_year: ay, school: school)).to be_truthy + it 'returns the average of the likert scores of the survey items' do + expect(SurveyItemResponse.score(measure: measure, school: school, academic_year: ay)).to eq 4 end end @@ -29,24 +34,28 @@ describe SurveyItemResponse, type: :model do end end - it 'is falsey' do - expect(SurveyItemResponse.sufficient_data?(measure: measure, academic_year: ay, school: school)).to be_falsey + it 'returns nil' do + expect(SurveyItemResponse.score(measure: measure, school: school, academic_year: ay)).to be_nil end end end context 'when the measure includes only student data' do let(:student_survey_item_1) { create(:survey_item, survey_item_id: 's-question-1', measure: measure) } + let(:student_survey_item_2) { create(:survey_item, survey_item_id: 's-question-2', measure: measure) } context 'and there is sufficient student data' do before :each do - SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD.times do - create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school) + (SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD/4).times do + create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 1) + create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 5) + create(:survey_item_response, survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: 1) + create(:survey_item_response, survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: 5) end end - it 'is truthy' do - expect(SurveyItemResponse.sufficient_data?(measure: measure, academic_year: ay, school: school)).to be_truthy + it 'returns the average of the likert scores of the survey items' do + expect(SurveyItemResponse.score(measure: measure, school: school, academic_year: ay)).to eq 3 end end @@ -57,8 +66,8 @@ describe SurveyItemResponse, type: :model do end end - it 'is falsey' do - expect(SurveyItemResponse.sufficient_data?(measure: measure, academic_year: ay, school: school)).to be_falsey + it 'returns nil' do + expect(SurveyItemResponse.score(measure: measure, school: school, academic_year: ay)).to be_nil end end end @@ -70,15 +79,15 @@ describe SurveyItemResponse, type: :model do context 'and there is sufficient teacher data and sufficient student data' do before :each do SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD.times do - create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school) + create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 5) end SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD.times do - create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school) + create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 5) end end - it 'is truthy' do - expect(SurveyItemResponse.sufficient_data?(measure: measure, academic_year: ay, school: school)).to be_truthy + it 'returns the average of the likert scores of the survey items' do + expect(SurveyItemResponse.score(measure: measure, school: school, academic_year: ay)).to eq 5 end end @@ -92,8 +101,8 @@ describe SurveyItemResponse, type: :model do end end - it 'is falsey' do - expect(SurveyItemResponse.sufficient_data?(measure: measure, academic_year: ay, school: school)).to be_falsey + it 'returns nil' do + expect(SurveyItemResponse.score(measure: measure, school: school, academic_year: ay)).to be_nil end end @@ -107,8 +116,8 @@ describe SurveyItemResponse, type: :model do end end - it 'is falsey' do - expect(SurveyItemResponse.sufficient_data?(measure: measure, academic_year: ay, school: school)).to be_falsey + it 'returns nil' do + expect(SurveyItemResponse.score(measure: measure, school: school, academic_year: ay)).to be_nil end end @@ -122,8 +131,8 @@ describe SurveyItemResponse, type: :model do end end - it 'is falsey' do - expect(SurveyItemResponse.sufficient_data?(measure: measure, academic_year: ay, school: school)).to be_falsey + it 'returns nil' do + expect(SurveyItemResponse.score(measure: measure, school: school, academic_year: ay)).to be_nil end end end