From 67d51aff5eb4a96d93c678c4283301ac8cad833f Mon Sep 17 00:00:00 2001 From: rebuilt Date: Wed, 2 Feb 2022 11:04:30 +0100 Subject: [PATCH] Refactor response rate --- app/models/response_rate.rb | 64 ++----------------------- app/models/student_response_rate.rb | 27 +++++++++++ app/models/teacher_response_rate.rb | 31 ++++++++++++ app/presenters/subcategory_presenter.rb | 7 +-- spec/models/response_rate_spec.rb | 20 ++++---- 5 files changed, 75 insertions(+), 74 deletions(-) create mode 100644 app/models/student_response_rate.rb create mode 100644 app/models/teacher_response_rate.rb diff --git a/app/models/response_rate.rb b/app/models/response_rate.rb index 825c7238..f66db842 100644 --- a/app/models/response_rate.rb +++ b/app/models/response_rate.rb @@ -5,71 +5,13 @@ class ResponseRate @academic_year = academic_year end - def student - rate(survey_item_count: student_survey_item_count, response_count: student_response_count, - total_possible_responses: total_possible_student_responses) - end - - def teacher - response_rate = rate(survey_item_count: teacher_survey_item_count, response_count: teacher_response_count, - total_possible_responses: total_possible_teacher_responses) - cap_at_100(response_rate) - end - - private - - def cap_at_100(response_rate) - response_rate > 100 ? 100 : response_rate - end - - def rate(survey_item_count:, response_count:, total_possible_responses:) + def rate return 0 unless survey_item_count.positive? - average_responses_per_survey_item = response_count / survey_item_count + average_responses_per_survey_item = response_count / survey_item_count.to_f return 0 unless total_possible_responses.positive? - (average_responses_per_survey_item / total_possible_responses * 100).round - end - - def total_possible_student_responses - @total_possible_student_responses ||= total_possible_responses do |responses| - responses.total_students - end - end - - def total_possible_teacher_responses - @total_possible_teacher_responses ||= total_possible_responses do |responses| - responses.total_teachers - end - end - - def total_possible_responses - total_responses = Respondent.where(school: @school, academic_year: @academic_year).first - return 0 unless total_responses.present? - - yield total_responses - end - - def student_response_count - @student_response_count ||= SurveyItemResponse.student_responses_for_measures(@subcategory.measures, @school, - @academic_year).count.to_f - end - - def teacher_response_count - @teacher_response_count ||= SurveyItemResponse.teacher_responses_for_measures(@subcategory.measures, @school, - @academic_year).count.to_f - end - - def student_survey_item_count - @student_survey_item_count ||= @subcategory.measures.map do |measure| - measure.student_survey_items.count - end.sum.to_f - end - - def teacher_survey_item_count - @teacher_survey_item_count ||= @subcategory.measures.map do |measure| - measure.teacher_survey_items.count - end.sum.to_f + (average_responses_per_survey_item / total_possible_responses.to_f * 100).round end end diff --git a/app/models/student_response_rate.rb b/app/models/student_response_rate.rb new file mode 100644 index 00000000..b8d38aca --- /dev/null +++ b/app/models/student_response_rate.rb @@ -0,0 +1,27 @@ +class StudentResponseRate < ResponseRate + def rate + super + end + + private + + def survey_item_count + @student_survey_item_count ||= @subcategory.measures.map do |measure| + measure.student_survey_items.count + end.sum + end + + def response_count + @student_response_count ||= SurveyItemResponse.student_responses_for_measures(@subcategory.measures, @school, + @academic_year).count + end + + def total_possible_responses + @total_possible_student_responses ||= begin + total_responses = Respondent.where(school: @school, academic_year: @academic_year).first + return 0 unless total_responses.present? + + total_responses.total_students + end + end +end diff --git a/app/models/teacher_response_rate.rb b/app/models/teacher_response_rate.rb new file mode 100644 index 00000000..9cce3a29 --- /dev/null +++ b/app/models/teacher_response_rate.rb @@ -0,0 +1,31 @@ +class TeacherResponseRate < ResponseRate + def rate + cap_at_100(super) + end + + private + + def cap_at_100(response_rate) + response_rate > 100 ? 100 : response_rate + end + + def survey_item_count + @teacher_survey_item_count ||= @subcategory.measures.map do |measure| + measure.teacher_survey_items.count + end.sum + end + + def response_count + @teacher_response_count ||= SurveyItemResponse.teacher_responses_for_measures(@subcategory.measures, @school, + @academic_year).count + end + + def total_possible_responses + @total_possible_teacher_responses ||= begin + total_responses = Respondent.where(school: @school, academic_year: @academic_year).first + return 0 unless total_responses.present? + + total_responses.total_teachers + end + end +end diff --git a/app/presenters/subcategory_presenter.rb b/app/presenters/subcategory_presenter.rb index f060312d..71729e43 100644 --- a/app/presenters/subcategory_presenter.rb +++ b/app/presenters/subcategory_presenter.rb @@ -3,7 +3,8 @@ class SubcategoryPresenter @subcategory = subcategory @academic_year = academic_year @school = school - @response_rate = ResponseRate.new(subcategory: @subcategory, school: @school, academic_year: @academic_year) + @student_response_rate = StudentResponseRate.new(subcategory: @subcategory, school: @school, academic_year: @academic_year) + @teacher_response_rate = TeacherResponseRate.new(subcategory: @subcategory, school: @school, academic_year: @academic_year) end def id @@ -32,11 +33,11 @@ class SubcategoryPresenter end def student_response_rate - @response_rate.student + @student_response_rate.rate end def teacher_response_rate - @response_rate.teacher + @teacher_response_rate.rate end def measure_presenters diff --git a/spec/models/response_rate_spec.rb b/spec/models/response_rate_spec.rb index 367a936c..ab81082c 100644 --- a/spec/models/response_rate_spec.rb +++ b/spec/models/response_rate_spec.rb @@ -8,7 +8,7 @@ describe ResponseRate, type: :model do total_teachers: SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, academic_year: ay) end - describe '.student' do + describe StudentResponseRate do let(:subcategory) { create(:subcategory) } let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) } let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) } @@ -35,13 +35,13 @@ describe ResponseRate, type: :model do context 'when the average number of student responses per question in a subcategory is equal to the student response threshold' do it 'returns 100 percent' do - expect(ResponseRate.new(subcategory: subcategory, school: school, - academic_year: ay).student).to eq 100 + expect(StudentResponseRate.new(subcategory: subcategory, school: school, + academic_year: ay).rate).to eq 100 end end end - describe '.teacher' do + describe TeacherResponseRate do let(:subcategory) { create(:subcategory) } let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) } let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) } @@ -69,8 +69,8 @@ describe ResponseRate, type: :model do context 'when the average number of teacher responses per question in a subcategory is equal to the total possible responses' do it 'returns 100 percent' do - expect(ResponseRate.new(subcategory: subcategory, school: school, - academic_year: ay).teacher).to eq 100 + expect(TeacherResponseRate.new(subcategory: subcategory, school: school, + academic_year: ay).rate).to eq 100 end end @@ -80,8 +80,8 @@ describe ResponseRate, type: :model do academic_year: ay, school: school, likert_score: 1) end it 'returns 10 percent' do - expect(ResponseRate.new(subcategory: subcategory, school: school, - academic_year: ay).teacher).to eq 78 + expect(TeacherResponseRate.new(subcategory: subcategory, school: school, + academic_year: ay).rate).to eq 78 end end @@ -91,8 +91,8 @@ describe ResponseRate, type: :model do academic_year: ay, school: school, likert_score: 1) end it 'returns 100 percent' do - expect(ResponseRate.new(subcategory: subcategory, school: school, - academic_year: ay).teacher).to eq 100 + expect(TeacherResponseRate.new(subcategory: subcategory, school: school, + academic_year: ay).rate).to eq 100 end end end