From f3fddd67b0aeecb41487794237cfe71f7dbe1d22 Mon Sep 17 00:00:00 2001 From: Nelson Jovel Date: Tue, 26 Dec 2023 16:23:29 -0800 Subject: [PATCH] perf: reduce number of queries for respondents --- app/models/report/subcategory.rb | 24 +++++++++---------- app/models/respondent.rb | 8 +++++++ app/models/response_rate_calculator.rb | 2 +- app/models/school.rb | 2 +- .../column/grouped_bar_column_presenter.rb | 2 +- app/presenters/response_rate_presenter.rb | 2 +- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/app/models/report/subcategory.rb b/app/models/report/subcategory.rb index 9c3d1af0..4679df81 100644 --- a/app/models/report/subcategory.rb +++ b/app/models/report/subcategory.rb @@ -1,10 +1,10 @@ module Report class Subcategory - def self.create_report(schools: School.all.includes(:district), academic_years: AcademicYear.all, subcategories: ::Subcategory.all, filename: 'subcategories.csv') + def self.create_report(schools: School.all.includes(:district), academic_years: AcademicYear.all, subcategories: ::Subcategory.all, filename: "subcategories.csv") data = [] mutex = Thread::Mutex.new - data << ['District', 'School', 'School Code', 'Academic Year', 'Recorded Date Range', 'Grades', 'Subcategory', 'Student Score', 'Student Zone', 'Teacher Score', - 'Teacher Zone', 'Admin Score', 'Admin Zone', 'All Score (Average)', 'All Score Zone'] + data << ["District", "School", "School Code", "Academic Year", "Recorded Date Range", "Grades", "Subcategory", "Student Score", "Student Zone", "Teacher Score", + "Teacher Zone", "Admin Score", "Admin Zone", "All Score (Average)", "All Score Zone"] pool_size = 2 jobs = Queue.new schools.each { |school| jobs << school } @@ -14,7 +14,7 @@ module Report while school = jobs.pop(true) academic_years.each do |academic_year| subcategories.each do |subcategory| - respondents = Respondent.find_by(school:, academic_year:) + respondents = Respondent.by_school_and_year(school:, academic_year:) next if respondents.nil? response_rate = subcategory.response_rate(school:, academic_year:) @@ -58,8 +58,8 @@ module Report end workers.each(&:join) - FileUtils.mkdir_p Rails.root.join('tmp', 'reports') - filepath = Rails.root.join('tmp', 'reports', filename) + FileUtils.mkdir_p Rails.root.join("tmp", "reports") + filepath = Rails.root.join("tmp", "reports", filename) write_csv(data:, filepath:) data end @@ -76,7 +76,7 @@ module Report def self.student_score(row:) row in [response_rate, subcategory, school, academic_year] student_score = subcategory.student_score(school:, academic_year:) if response_rate.meets_student_threshold? - student_score || 'N/A' + student_score || "N/A" end def self.student_zone(row:) @@ -86,14 +86,14 @@ module Report academic_year:).type.to_s.capitalize end - student_zone || 'N/A' + student_zone || "N/A" end def self.teacher_score(row:) row in [response_rate, subcategory, school, academic_year] teacher_score = subcategory.teacher_score(school:, academic_year:) if response_rate.meets_teacher_threshold? - teacher_score || 'N/A' + teacher_score || "N/A" end def self.teacher_zone(row:) @@ -102,20 +102,20 @@ module Report teacher_zone = subcategory.teacher_zone(school:, academic_year:).type.to_s.capitalize end - teacher_zone || 'N/A' + teacher_zone || "N/A" end def self.admin_score(row:) row in [response_rate, subcategory, school, academic_year] admin_score = subcategory.admin_score(school:, academic_year:) - admin_score = 'N/A' unless admin_score >= 0 + admin_score = "N/A" unless admin_score >= 0 admin_score end def self.admin_zone(row:) row in [response_rate, subcategory, school, academic_year] tmp_zone = subcategory.admin_zone(school:, academic_year:).type - tmp_zone == :insufficient_data ? 'N/A' : tmp_zone.to_s.capitalize + tmp_zone == :insufficient_data ? "N/A" : tmp_zone.to_s.capitalize end end end diff --git a/app/models/respondent.rb b/app/models/respondent.rb index fb5d3277..8afd9c03 100644 --- a/app/models/respondent.rb +++ b/app/models/respondent.rb @@ -16,4 +16,12 @@ class Respondent < ApplicationRecord end end end + + def self.by_school_and_year(school:, academic_year:) + @by_school_and_year ||= Hash.new do |memo, (school, academic_year)| + memo[[school, academic_year]] = Respondent.find_by(school:, academic_year:) + end + + @by_school_and_year[[school, academic_year]] + end end diff --git a/app/models/response_rate_calculator.rb b/app/models/response_rate_calculator.rb index a18566d7..1ec9fbc8 100644 --- a/app/models/response_rate_calculator.rb +++ b/app/models/response_rate_calculator.rb @@ -40,7 +40,7 @@ class ResponseRateCalculator end def respondents - @respondents ||= Respondent.find_by(school:, academic_year:) + @respondents ||= Respondent.by_school_and_year(school:, academic_year:) end def population_data_unavailable? diff --git a/app/models/school.rb b/app/models/school.rb index c883706c..641d2af4 100644 --- a/app/models/school.rb +++ b/app/models/school.rb @@ -21,6 +21,6 @@ class School < ApplicationRecord end def grades(academic_year:) - @grades ||= Respondent.find_by(school: self, academic_year:)&.enrollment_by_grade&.keys || (-1..12).to_a + @grades ||= Respondent.by_school_and_year(school: self, academic_year:)&.enrollment_by_grade&.keys || (-1..12).to_a end end diff --git a/app/presenters/analyze/graph/column/grouped_bar_column_presenter.rb b/app/presenters/analyze/graph/column/grouped_bar_column_presenter.rb index 88015d2e..1206fccc 100644 --- a/app/presenters/analyze/graph/column/grouped_bar_column_presenter.rb +++ b/app/presenters/analyze/graph/column/grouped_bar_column_presenter.rb @@ -138,7 +138,7 @@ module Analyze end def grades(year_index) - Respondent.find_by(school:, academic_year: academic_years[year_index]).enrollment_by_grade.keys + Respondent.by_school_and_year(school:, academic_year: academic_years[year_index]).enrollment_by_grade.keys end private diff --git a/app/presenters/response_rate_presenter.rb b/app/presenters/response_rate_presenter.rb index 07381e28..3028e1bb 100644 --- a/app/presenters/response_rate_presenter.rb +++ b/app/presenters/response_rate_presenter.rb @@ -99,7 +99,7 @@ class ResponseRatePresenter end def respondents - Respondent.find_by(school:, academic_year:) + @respondents ||= Respondent.by_school_and_year(school:, academic_year:) end def grades