diff --git a/app/javascript/controllers/analyze_controller.js b/app/javascript/controllers/analyze_controller.js index 7a1f0721..e4c08675 100644 --- a/app/javascript/controllers/analyze_controller.js +++ b/app/javascript/controllers/analyze_controller.js @@ -1,21 +1,19 @@ -import { Controller } from "@hotwired/stimulus" +import { Controller } from "@hotwired/stimulus"; // Connects to data-controller="analyze" export default class extends Controller { - connect() { } + connect() {} refresh(event) { - let location = event.target.value+ "&academic_years="; - let year_checkboxes = document.getElementsByName("year-checkbox"); - let selected_years = []; + let location = event.target.value; + let year_checkboxes = [...document.getElementsByName("year-checkbox")]; - let ending = ""; - year_checkboxes.forEach((item)=>{ - if(item.checked) { - selected_years.push(item.id) - } - }) - - console.log(location) - window.location = location + selected_years.join(",") + let selected_years = year_checkboxes + .filter((item) => { + return item.checked; + }) + .map((item) => { + return item.id; + }); + window.location = location + "&academic_years=" + selected_years.join(","); } } diff --git a/app/models/measure.rb b/app/models/measure.rb index e05c6684..cd97a291 100644 --- a/app/models/measure.rb +++ b/app/models/measure.rb @@ -1,5 +1,5 @@ class Measure < ActiveRecord::Base - belongs_to :subcategory + belongs_to :subcategory, counter_cache: true has_one :category, through: :subcategory has_many :scales has_many :admin_data_items, through: :scales @@ -203,14 +203,23 @@ class Measure < ActiveRecord::Base end def sufficient_student_data?(school:, academic_year:) - return false unless includes_student_survey_items? + return @sufficient_student_data ||= false unless includes_student_survey_items? + return @sufficient_student_data ||= false if student_survey_items_by_survey_type(school:, + academic_year:).all? do |survey_item| + survey_item.survey_item_responses.where(school:, + academic_year:).none? + end - @sufficient_student_data ||= subcategory.response_rate(school:, academic_year:).meets_student_threshold + @sufficient_student_data ||= subcategory.response_rate(school:, academic_year:).meets_student_threshold? end def sufficient_teacher_data?(school:, academic_year:) - return false unless includes_teacher_survey_items? + return @sufficient_teacher_data ||= false unless includes_teacher_survey_items? + return @sufficient_teacher_data ||= false if teacher_survey_items.all? do |survey_item| + survey_item.survey_item_responses.where(school:, + academic_year:).none? + end - @sufficient_teacher_data ||= subcategory.response_rate(school:, academic_year:).meets_teacher_threshold + @sufficient_teacher_data ||= subcategory.response_rate(school:, academic_year:).meets_teacher_threshold? end end diff --git a/app/models/scale.rb b/app/models/scale.rb index 7a6415d3..a33479c8 100644 --- a/app/models/scale.rb +++ b/app/models/scale.rb @@ -1,5 +1,5 @@ class Scale < ApplicationRecord - belongs_to :measure + belongs_to :measure, counter_cache: true has_many :survey_items has_many :survey_item_responses, through: :survey_items has_many :admin_data_items diff --git a/app/models/subcategory.rb b/app/models/subcategory.rb index 29f36333..2a670def 100644 --- a/app/models/subcategory.rb +++ b/app/models/subcategory.rb @@ -1,5 +1,5 @@ class Subcategory < ActiveRecord::Base - belongs_to :category + belongs_to :category, counter_cache: true has_many :measures diff --git a/app/models/survey_item.rb b/app/models/survey_item.rb index 944d35a9..88ee2029 100644 --- a/app/models/survey_item.rb +++ b/app/models/survey_item.rb @@ -1,5 +1,5 @@ class SurveyItem < ActiveRecord::Base - belongs_to :scale + belongs_to :scale, counter_cache: true has_one :measure, through: :scale has_one :subcategory, through: :measure diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index 3e61a12b..f70dcfbf 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -4,7 +4,7 @@ class SurveyItemResponse < ActiveRecord::Base belongs_to :academic_year belongs_to :school - belongs_to :survey_item + belongs_to :survey_item, counter_cache: true has_one :measure, through: :survey_item scope :exclude_boston, lambda { diff --git a/app/services/response_rate_loader.rb b/app/services/response_rate_loader.rb index d04528db..7d9906a0 100644 --- a/app/services/response_rate_loader.rb +++ b/app/services/response_rate_loader.rb @@ -1,5 +1,5 @@ class ResponseRateLoader - def self.refresh + def self.reset schools = School.all academic_years = AcademicYear.all subcategories = Subcategory.all diff --git a/db/migrate/20220616211049_add_survey_item_responses_count_to_survey_item.rb b/db/migrate/20220616211049_add_survey_item_responses_count_to_survey_item.rb new file mode 100644 index 00000000..92d87268 --- /dev/null +++ b/db/migrate/20220616211049_add_survey_item_responses_count_to_survey_item.rb @@ -0,0 +1,5 @@ +class AddSurveyItemResponsesCountToSurveyItem < ActiveRecord::Migration[7.0] + def change + add_column :survey_items, :survey_item_responses_count, :integer + end +end diff --git a/db/migrate/20220616211211_reset_all_survey_item_cache_counters.rb b/db/migrate/20220616211211_reset_all_survey_item_cache_counters.rb new file mode 100644 index 00000000..54f8f491 --- /dev/null +++ b/db/migrate/20220616211211_reset_all_survey_item_cache_counters.rb @@ -0,0 +1,9 @@ +class ResetAllSurveyItemCacheCounters < ActiveRecord::Migration[7.0] + def up + SurveyItem.all.each do |survey_item| + SurveyItem.reset_counters(survey_item.id, :survey_item_responses) + end + end + + def down; end +end diff --git a/db/migrate/20220616214126_add_survey_items_count_to_scales.rb b/db/migrate/20220616214126_add_survey_items_count_to_scales.rb new file mode 100644 index 00000000..0ef1c608 --- /dev/null +++ b/db/migrate/20220616214126_add_survey_items_count_to_scales.rb @@ -0,0 +1,5 @@ +class AddSurveyItemsCountToScales < ActiveRecord::Migration[7.0] + def change + add_column :scales, :survey_items_count, :integer + end +end diff --git a/db/migrate/20220616214236_reset_all_scale_cache_counters.rb b/db/migrate/20220616214236_reset_all_scale_cache_counters.rb new file mode 100644 index 00000000..edb4497c --- /dev/null +++ b/db/migrate/20220616214236_reset_all_scale_cache_counters.rb @@ -0,0 +1,9 @@ +class ResetAllScaleCacheCounters < ActiveRecord::Migration[7.0] + def up + Scale.all.each do |scale| + Scale.reset_counters(scale.id, :survey_items) + end + end + + def down; end +end diff --git a/db/migrate/20220616214910_add_scales_count_to_measures.rb b/db/migrate/20220616214910_add_scales_count_to_measures.rb new file mode 100644 index 00000000..fc7b8bc7 --- /dev/null +++ b/db/migrate/20220616214910_add_scales_count_to_measures.rb @@ -0,0 +1,5 @@ +class AddScalesCountToMeasures < ActiveRecord::Migration[7.0] + def change + add_column :measures, :scales_count, :integer + end +end diff --git a/db/migrate/20220616215010_reset_all_measure_cache_counters.rb b/db/migrate/20220616215010_reset_all_measure_cache_counters.rb new file mode 100644 index 00000000..edfac83b --- /dev/null +++ b/db/migrate/20220616215010_reset_all_measure_cache_counters.rb @@ -0,0 +1,9 @@ +class ResetAllMeasureCacheCounters < ActiveRecord::Migration[7.0] + def up + Measure.all.each do |measure| + Measure.reset_counters(measure.id, :scales) + end + end + + def down; end +end diff --git a/db/migrate/20220616215452_add_measures_count_to_subcategories.rb b/db/migrate/20220616215452_add_measures_count_to_subcategories.rb new file mode 100644 index 00000000..cae8d4a7 --- /dev/null +++ b/db/migrate/20220616215452_add_measures_count_to_subcategories.rb @@ -0,0 +1,5 @@ +class AddMeasuresCountToSubcategories < ActiveRecord::Migration[7.0] + def change + add_column :subcategories, :measures_count, :integer + end +end diff --git a/db/migrate/20220616215952_reset_all_subcategory_cache_counters.rb b/db/migrate/20220616215952_reset_all_subcategory_cache_counters.rb new file mode 100644 index 00000000..c6102e38 --- /dev/null +++ b/db/migrate/20220616215952_reset_all_subcategory_cache_counters.rb @@ -0,0 +1,9 @@ +class ResetAllSubcategoryCacheCounters < ActiveRecord::Migration[7.0] + def up + Subcategory.all.each do |subcategory| + Subcategory.reset_counters(subcategory.id, :measures) + end + end + + def down; end +end diff --git a/db/migrate/20220616220306_add_subcategories_count_to_categories.rb b/db/migrate/20220616220306_add_subcategories_count_to_categories.rb new file mode 100644 index 00000000..13f285a1 --- /dev/null +++ b/db/migrate/20220616220306_add_subcategories_count_to_categories.rb @@ -0,0 +1,5 @@ +class AddSubcategoriesCountToCategories < ActiveRecord::Migration[7.0] + def change + add_column :categories, :subcategories_count, :integer + end +end diff --git a/db/migrate/20220616220352_reset_all_category_cache_counters.rb b/db/migrate/20220616220352_reset_all_category_cache_counters.rb new file mode 100644 index 00000000..003b3808 --- /dev/null +++ b/db/migrate/20220616220352_reset_all_category_cache_counters.rb @@ -0,0 +1,9 @@ +class ResetAllCategoryCacheCounters < ActiveRecord::Migration[7.0] + def up + Category.all.each do |category| + Category.reset_counters(category.id, :subcategories) + end + end + + def down; end +end diff --git a/db/schema.rb b/db/schema.rb index 8636cde0..10524193 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2022_06_14_211616) do +ActiveRecord::Schema[7.0].define(version: 2022_06_16_220352) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -57,6 +57,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_14_211616) do t.datetime "updated_at", null: false t.string "category_id", null: false t.string "short_description" + t.integer "subcategories_count" t.index ["slug"], name: "index_categories_on_slug", unique: true end @@ -283,6 +284,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_14_211616) do t.text "description" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "scales_count" t.index ["measure_id"], name: "index_measures_on_measure_id" t.index ["subcategory_id"], name: "index_measures_on_subcategory_id" end @@ -319,6 +321,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_14_211616) do t.bigint "measure_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "survey_items_count" t.index ["measure_id"], name: "index_scales_on_measure_id" t.index ["scale_id"], name: "index_scales_on_scale_id", unique: true end @@ -343,6 +346,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_14_211616) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "subcategory_id", null: false + t.integer "measures_count" end create_table "survey_item_responses", id: :serial, force: :cascade do |t| @@ -371,6 +375,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_14_211616) do t.float "ideal_low_benchmark" t.bigint "scale_id", null: false t.boolean "on_short_form", default: false + t.integer "survey_item_responses_count" t.index ["scale_id"], name: "index_survey_items_on_scale_id" t.index ["survey_item_id"], name: "index_survey_items_on_survey_item_id" end diff --git a/lib/tasks/data.rake b/lib/tasks/data.rake index 84bff1d1..52b30f7c 100644 --- a/lib/tasks/data.rake +++ b/lib/tasks/data.rake @@ -49,9 +49,9 @@ namespace :data do end desc 'refresh response rate values' - task refresh_response_rates: :environment do + task reset_response_rates: :environment do puts 'Refreshing response rates' - ResponseRateLoader.refresh + ResponseRateLoader.reset puts "=====================> Completed loading #{ResponseRate.count} survey responses" end @@ -63,6 +63,31 @@ namespace :data do end puts "=====================> Completed loading #{AdminDataValue.count} survey responses" end + + desc 'reset all cache counters' + task reset_cache_counters: :environment do + puts '=====================> Resetting Category counters' + Category.all.each do |category| + Category.reset_counters(category.id, :subcategories) + end + puts '=====================> Resetting Subcategory counters' + Subcategory.all.each do |subcategory| + Subcategory.reset_counters(subcategory.id, :measures) + end + puts '=====================> Resetting Measure counters' + Measure.all.each do |measure| + Measure.reset_counters(measure.id, :scales) + end + puts '=====================> Resetting Scale counters' + Scale.all.each do |scale| + Scale.reset_counters(scale.id, :survey_items) + end + puts '=====================> Resetting SurveyItem counters' + SurveyItem.all.each do |survey_item| + SurveyItem.reset_counters(survey_item.id, :survey_item_responses) + end + end + desc 'Load in all data' task load: :environment do # return if School.count > 0 diff --git a/spec/services/response_rate_loader_spec.rb b/spec/services/response_rate_loader_spec.rb index 4b6e49ae..2ebde200 100644 --- a/spec/services/response_rate_loader_spec.rb +++ b/spec/services/response_rate_loader_spec.rb @@ -44,7 +44,7 @@ describe ResponseRateLoader do DatabaseCleaner.clean end - describe 'self.refresh' do + describe 'self.reset' do context 'When refreshing response rates' do context 'and half the students responded to each question' do before :each do @@ -58,7 +58,7 @@ describe ResponseRateLoader do create_list(:survey_item_response, 5, survey_item: t_phya_q2, likert_score: 3, school:, academic_year:) create_list(:survey_item_response, 5, survey_item: t_phya_q3, likert_score: 3, school:, academic_year:) - ResponseRateLoader.refresh + ResponseRateLoader.reset end it 'populates the database with response rates' do @@ -76,7 +76,7 @@ describe ResponseRateLoader do context 'when running the loader a second time' do it 'is idempotent' do response_count = ResponseRate.count - ResponseRateLoader.refresh + ResponseRateLoader.reset second_count = ResponseRate.count expect(response_count).to eq second_count @@ -90,7 +90,7 @@ describe ResponseRateLoader do create_list(:survey_item_response, 5, survey_item: s_poaf_q1, likert_score: 3, school:, academic_year:) create_list(:survey_item_response, 5, survey_item: t_phya_q2, likert_score: 3, school:, academic_year:) - ResponseRateLoader.refresh + ResponseRateLoader.reset end it 'only takes into account the first question and ignores the other questions in the scale' do @@ -106,7 +106,7 @@ describe ResponseRateLoader do create_list(:survey_item_response, 5, survey_item: s_poaf_q1, likert_score: 3, school:, academic_year:) create_list(:survey_item_response, 5, survey_item: t_phya_q2, likert_score: 3, school:, academic_year:) - ResponseRateLoader.refresh + ResponseRateLoader.reset end it 'since no score can be calculated, it returns a default of 100' do @@ -128,7 +128,7 @@ describe ResponseRateLoader do create_list(:survey_item_response, 1, survey_item: t_phya_q3, likert_score: 3, school:, academic_year:) short_form_survey - ResponseRateLoader.refresh + ResponseRateLoader.reset end it 'only counts responses from survey items on the short form' do diff --git a/spec/views/analyze/index.html.erb_spec.rb b/spec/views/analyze/index.html.erb_spec.rb index 4a49dc94..3e73ea04 100644 --- a/spec/views/analyze/index.html.erb_spec.rb +++ b/spec/views/analyze/index.html.erb_spec.rb @@ -107,7 +107,7 @@ describe 'analyze/index' do end it 'displays disabled checkboxes for years that dont have data' do - ResponseRateLoader.refresh + ResponseRateLoader.reset year_checkbox = subject.css("##{academic_year.range}").first expect(year_checkbox.name).to eq 'input' expect(academic_year.range).to eq '2050-51'