diff --git a/app/models/response_rate.rb b/app/models/response_rate.rb
new file mode 100644
index 00000000..20f39759
--- /dev/null
+++ b/app/models/response_rate.rb
@@ -0,0 +1,88 @@
+class ResponseRate
+ def initialize(subcategory:, school:, academic_year:)
+ @subcategory = subcategory
+ @school = school
+ @academic_year = academic_year
+ end
+
+ def student
+ @student_response_rate ||= begin
+ return 0 unless student_survey_item_count.positive?
+
+ average_responses_per_survey_item = student_response_count / student_survey_item_count
+
+ return 0 unless total_possible_student_responses.positive?
+
+ (average_responses_per_survey_item / total_possible_student_responses * 100).round
+ end
+ end
+
+ def teacher
+ @teacher_response_rate ||= begin
+ return 0 unless teacher_survey_item_count.positive?
+
+ average_responses_per_survey_item = teacher_response_count / teacher_survey_item_count
+
+ return 0 unless total_possible_teacher_responses.positive?
+
+ (average_responses_per_survey_item / total_possible_teacher_responses * 100).round
+ end
+ end
+
+ private
+
+ 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 ||= response_count do |measure|
+ next 0 unless measure.includes_student_survey_items?
+
+ SurveyItemResponse.student_responses_for_measure(measure, @school, @academic_year).count
+ end
+ end
+
+ def teacher_response_count
+ @teacher_response_count ||= response_count do |measure|
+ next 0 unless measure.includes_teacher_survey_items?
+
+ SurveyItemResponse.teacher_responses_for_measure(measure, @school, @academic_year).count
+ end
+ end
+
+ def response_count(&block)
+ @subcategory.measures.map(&block).sum
+ end
+
+ def student_survey_item_count
+ @student_survey_item_count ||= survey_item_count do |measure|
+ measure.student_survey_items.count
+ end
+ end
+
+ def teacher_survey_item_count
+ @teacher_survey_item_count ||= survey_item_count do |measure|
+ measure.teacher_survey_items.count
+ end
+ end
+
+ def survey_item_count(&block)
+ @subcategory.measures.map(&block).sum
+ end
+end
diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb
index 76f663b7..838bc481 100644
--- a/app/models/survey_item_response.rb
+++ b/app/models/survey_item_response.rb
@@ -16,21 +16,6 @@ class SurveyItemResponse < ActiveRecord::Base
end.average
end
- def self.average_number_of_student_respondents(subcategory:, school:, academic_year:)
- response_count = subcategory.measures.map do |measure|
- next 0 unless measure.includes_student_survey_items?
-
- SurveyItemResponse.student_responses_for_measure(measure, school, academic_year).count
- end.sum
-
- survey_item_count = subcategory.measures.map do |measure|
- measure.student_survey_items.count
- end.sum
- return 0 unless survey_item_count.positive?
-
- response_count / survey_item_count
- end
-
def self.measures_with_sufficient_data(subcategory:, school:, academic_year:)
subcategory.measures.select do |measure|
sufficient_data?(measure: measure, school: school, academic_year: academic_year)
diff --git a/app/presenters/subcategory_presenter.rb b/app/presenters/subcategory_presenter.rb
index 721bee0b..f060312d 100644
--- a/app/presenters/subcategory_presenter.rb
+++ b/app/presenters/subcategory_presenter.rb
@@ -3,6 +3,7 @@ class SubcategoryPresenter
@subcategory = subcategory
@academic_year = academic_year
@school = school
+ @response_rate = ResponseRate.new(subcategory: @subcategory, school: @school, academic_year: @academic_year)
end
def id
@@ -31,10 +32,11 @@ class SubcategoryPresenter
end
def student_response_rate
- @student_response_rate ||= response_rate(type: :total_students) do
- SurveyItemResponse.average_number_of_student_respondents(subcategory: @subcategory, school: @school,
- academic_year: @academic_year)
- end
+ @response_rate.student
+ end
+
+ def teacher_response_rate
+ @response_rate.teacher
end
def measure_presenters
@@ -57,16 +59,4 @@ class SubcategoryPresenter
def measures
@measures ||= @subcategory.measures.includes([:admin_data_items]).order(:measure_id)
end
-
- def response_rate(type:)
- number_of_responses = yield
- total_responses = Respondent.where(school: @school, academic_year: @academic_year).first
- return 0 unless total_responses.present?
-
- total_possible_responses = total_responses.send(type)
-
- return 0 if number_of_responses.nil? || total_possible_responses == 0
-
- (number_of_responses / total_possible_responses * 100).round
- end
end
diff --git a/app/views/categories/_subcategory_section.html.erb b/app/views/categories/_subcategory_section.html.erb
index 797af55e..06708d08 100644
--- a/app/views/categories/_subcategory_section.html.erb
+++ b/app/views/categories/_subcategory_section.html.erb
@@ -15,13 +15,10 @@
<%= subcategory.student_response_rate %>%
of students responded
- <%# %>
- <%#
<%= subcategory.teacher_response_rate %1>%
%>
- <%#
of teachers responded
%>
- <%#
%>
- <%# <%= subcategory.total_teachers %1> %>
- <%#
%>
- %#>
+
+
<%= subcategory.teacher_response_rate %>%
+
of teachers responded
+
diff --git a/spec/models/response_rate_spec.rb b/spec/models/response_rate_spec.rb
new file mode 100644
index 00000000..f703cae1
--- /dev/null
+++ b/spec/models/response_rate_spec.rb
@@ -0,0 +1,76 @@
+require 'rails_helper'
+
+describe ResponseRate, type: :model do
+ let(:school) { create(:school) }
+ let(:ay) { create(:academic_year) }
+ let(:survey_respondents) do
+ create(:respondent, school: school, total_students: SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
+ total_teachers: SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, academic_year: ay)
+ end
+
+ describe '.student' do
+ let(:subcategory) { create(:subcategory) }
+ let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) }
+ let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) }
+ let(:insufficient_measure) { create(:measure, subcategory: subcategory) }
+ let(:sufficient_teacher_survey_item) { create(:teacher_survey_item, measure: sufficient_measure_1) }
+ let(:sufficient_student_survey_item_1) { create(:student_survey_item, measure: sufficient_measure_1) }
+ let(:insufficient_teacher_survey_item) { create(:teacher_survey_item, measure: insufficient_measure) }
+ let(:sufficient_student_survey_item_2) { create(:student_survey_item, measure: sufficient_measure_2) }
+ let(:insufficient_student_survey_item) { create(:student_survey_item, measure: insufficient_measure) }
+
+ before :each do
+ survey_respondents
+ create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item,
+ academic_year: ay, school: school, likert_score: 1)
+ create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_1,
+ academic_year: ay, school: school, likert_score: 4)
+ create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD + 1, survey_item: sufficient_student_survey_item_2,
+ academic_year: ay, school: school, likert_score: 4)
+ create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1,
+ survey_item: insufficient_teacher_survey_item, academic_year: ay, school: school, likert_score: 1)
+ create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1,
+ survey_item: insufficient_student_survey_item, academic_year: ay, school: school, likert_score: 1)
+ end
+
+ 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
+ end
+ end
+ end
+
+ describe '.teacher' do
+ let(:subcategory) { create(:subcategory) }
+ let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) }
+ let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) }
+ let(:insufficient_measure) { create(:measure, subcategory: subcategory) }
+ let(:sufficient_teacher_survey_item_1) { create(:teacher_survey_item, measure: sufficient_measure_1) }
+ let(:sufficient_teacher_survey_item_2) { create(:teacher_survey_item, measure: sufficient_measure_1) }
+ let(:sufficient_student_survey_item_1) { create(:student_survey_item, measure: sufficient_measure_1) }
+ let(:insufficient_teacher_survey_item) { create(:teacher_survey_item, measure: insufficient_measure) }
+ let(:insufficient_student_survey_item) { create(:student_survey_item, measure: insufficient_measure) }
+
+ before :each do
+ survey_respondents
+ create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item_1,
+ academic_year: ay, school: school, likert_score: 1)
+ create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD + 1, survey_item: sufficient_teacher_survey_item_2,
+ academic_year: ay, school: school, likert_score: 1)
+ create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_1,
+ academic_year: ay, school: school, likert_score: 4)
+ create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1,
+ survey_item: insufficient_teacher_survey_item, academic_year: ay, school: school, likert_score: 1)
+ create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1,
+ survey_item: insufficient_student_survey_item, academic_year: ay, school: school, likert_score: 1)
+ end
+
+ 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).teacher).to eq 100
+ end
+ end
+ end
+end
diff --git a/spec/models/survey_item_response_spec.rb b/spec/models/survey_item_response_spec.rb
index d956f1ff..1e68125a 100644
--- a/spec/models/survey_item_response_spec.rb
+++ b/spec/models/survey_item_response_spec.rb
@@ -334,33 +334,4 @@ describe SurveyItemResponse, type: :model do
expect(SurveyItemResponse.responses_for_measure(measure: insufficient_measure, school: school, academic_year: ay)).to be nil
end
end
-
- describe '.average_number_of_student_respondents' do
- let(:subcategory) { create(:subcategory) }
- let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) }
- let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) }
- let(:insufficient_measure) { create(:measure, subcategory: subcategory) }
- let(:sufficient_teacher_survey_item) { create(:teacher_survey_item, measure: sufficient_measure_1) }
- let(:sufficient_student_survey_item_1) { create(:student_survey_item, measure: sufficient_measure_1) }
- let(:insufficient_teacher_survey_item) { create(:teacher_survey_item, measure: insufficient_measure) }
- let(:sufficient_student_survey_item_2) { create(:student_survey_item, measure: sufficient_measure_2) }
- let(:insufficient_student_survey_item) { create(:student_survey_item, measure: insufficient_measure) }
-
- before :each do
- create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item,
- academic_year: ay, school: school, likert_score: 1)
- create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_1,
- academic_year: ay, school: school, likert_score: 4)
- create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD + 1, survey_item: sufficient_student_survey_item_2,
- academic_year: ay, school: school, likert_score: 4)
- create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1,
- survey_item: insufficient_teacher_survey_item, academic_year: ay, school: school, likert_score: 1)
- create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1,
- survey_item: insufficient_student_survey_item, academic_year: ay, school: school, likert_score: 1)
- end
-
- it 'returns only responses in a measure that meets the low threshold' do
- expect(SurveyItemResponse.average_number_of_student_respondents(subcategory: subcategory, school: school, academic_year: ay)).to eq SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD
- end
- end
end