Create response rate model

pull/1/head
rebuilt 4 years ago
parent 0e9acc7467
commit 61aad20cb2

@ -0,0 +1,17 @@
class CreateResponseRates < ActiveRecord::Migration[7.0]
def change
create_table :response_rates do |t|
t.references :subcategory, null: false, foreign_key: true
t.references :school, null: false, foreign_key: true
t.references :academic_year, null: false, foreign_key: true
t.float :student_response_rate
t.float :teacher_response_rate
t.boolean :meets_student_threshold
t.boolean :meets_teacher_threshold
t.timestamps
end
add_index :response_rates, %i[school_id subcategory_id]
end
end

@ -10,9 +10,8 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2022_05_10_232626) do
ActiveRecord::Schema[7.0].define(version: 2022_06_14_211616) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "plpgsql"
create_table "academic_years", id: :serial, force: :cascade do |t|
@ -299,6 +298,22 @@ ActiveRecord::Schema[7.0].define(version: 2022_05_10_232626) do
t.index ["school_id"], name: "index_respondents_on_school_id"
end
create_table "response_rates", force: :cascade do |t|
t.bigint "subcategory_id", null: false
t.bigint "school_id", null: false
t.bigint "academic_year_id", null: false
t.float "student_response_rate"
t.float "teacher_response_rate"
t.boolean "meets_student_threshold"
t.boolean "meets_teacher_threshold"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["academic_year_id"], name: "index_response_rates_on_academic_year_id"
t.index ["school_id", "subcategory_id"], name: "index_response_rates_on_school_id_and_subcategory_id"
t.index ["school_id"], name: "index_response_rates_on_school_id"
t.index ["subcategory_id"], name: "index_response_rates_on_subcategory_id"
end
create_table "scales", force: :cascade do |t|
t.string "scale_id", null: false
t.bigint "measure_id", null: false
@ -340,6 +355,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_05_10_232626) do
t.datetime "updated_at", null: false
t.index ["academic_year_id"], name: "index_survey_item_responses_on_academic_year_id"
t.index ["response_id"], name: "index_survey_item_responses_on_response_id"
t.index ["school_id", "academic_year_id"], name: "index_survey_item_responses_on_school_id_and_academic_year_id"
t.index ["school_id"], name: "index_survey_item_responses_on_school_id"
t.index ["survey_item_id"], name: "index_survey_item_responses_on_survey_item_id"
end
@ -380,6 +396,9 @@ ActiveRecord::Schema[7.0].define(version: 2022_05_10_232626) do
add_foreign_key "measures", "subcategories"
add_foreign_key "respondents", "academic_years"
add_foreign_key "respondents", "schools"
add_foreign_key "response_rates", "academic_years"
add_foreign_key "response_rates", "schools"
add_foreign_key "response_rates", "subcategories"
add_foreign_key "scales", "measures"
add_foreign_key "schools", "districts"
add_foreign_key "subcategories", "categories"

@ -1,4 +1,14 @@
FactoryBot.define do
factory :response_rate do
subcategory { nil }
school { nil }
academic_year { nil }
student_response_rate { 1.5 }
teacher_response_rate { 1.5 }
meets_student_threshold { false }
meets_teacher_threshold { false }
end
factory :admin_data_value do
likert_score { 1.5 }
school

@ -1,183 +1,5 @@
require 'rails_helper'
describe ResponseRate, type: :model do
let(:school) { create(:school) }
let(:academic_year) { create(:academic_year) }
describe StudentResponseRate do
let(:subcategory) { create(:subcategory) }
let(:sufficient_measure_1) { create(:measure, subcategory:) }
let(:sufficient_scale_1) { create(:scale, measure: sufficient_measure_1) }
let(:sufficient_measure_2) { create(:measure, subcategory:) }
let(:sufficient_scale_2) { create(:scale, measure: sufficient_measure_2) }
let(:sufficient_teacher_survey_item) { create(:teacher_survey_item, scale: sufficient_scale_1) }
let(:sufficient_student_survey_item_1) { create(:student_survey_item, scale: sufficient_scale_1) }
let(:insufficient_student_survey_item_1) { create(:student_survey_item, scale: sufficient_scale_1) }
let(:sufficient_student_survey_item_2) { create(:student_survey_item, scale: sufficient_scale_2) }
before :each do
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item,
academic_year:, school:, likert_score: 1)
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_1,
academic_year:, school:, likert_score: 4)
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_2,
academic_year:, school:, likert_score: 4)
end
context 'when a students take a regular survey' do
before :each do
create(:respondent, school:, academic_year:)
create(:survey, school:, academic_year:)
end
context 'when the average number of student responses per question in a subcategory is equal to the student response threshold' do
it 'returns a response rate equal to the response threshold' do
expect(StudentResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 25
end
end
end
context 'when students take the short form survey' do
before :each do
create(:respondent, school:, academic_year:)
create(:survey, form: :short, school:, academic_year:)
end
context 'when the average number of student responses per question in a subcategory is equal to the student response threshold' do
before :each do
sufficient_student_survey_item_1.update! on_short_form: true
sufficient_student_survey_item_2.update! on_short_form: true
end
it 'returns 100 percent' do
expect(StudentResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 25
end
context 'for the same number of responses, if only one of the questions is a short form question, the response rate will be half' do
before do
sufficient_student_survey_item_2.update! on_short_form: false
end
it 'returns 100 percent' do
expect(StudentResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 50
end
end
end
end
context 'when the average number of teacher responses is greater than the total possible responses' do
before do
create(:respondent, school:, academic_year:)
create(:survey, school:, academic_year:)
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD * 11, survey_item: sufficient_student_survey_item_2,
academic_year:, school:, likert_score: 1)
end
it 'returns 100 percent' do
expect(StudentResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 100
end
end
context 'when no survey information exists for that school or year' do
it 'returns 100 percent' do
expect(StudentResponseRate.new(subcategory:, school:, academic_year:).rate).to eq 100
end
end
context 'when there is an imbalance in the response rate of the student items' do
context 'and one of the student items has no associated survey item responses' do
before do
create(:respondent, school:, academic_year:)
create(:survey, school:, academic_year:)
insufficient_student_survey_item_1
end
it 'ignores the empty survey item and returns only the average response rate of student survey items with responses' do
expect(StudentResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 25
end
end
end
end
describe TeacherResponseRate do
let(:subcategory) { create(:subcategory) }
let(:sufficient_measure_1) { create(:measure, subcategory:) }
let(:sufficient_scale_1) { create(:scale, measure: sufficient_measure_1) }
let(:sufficient_measure_2) { create(:measure, subcategory:) }
let(:sufficient_scale_2) { create(:scale, measure: sufficient_measure_2) }
let(:sufficient_teacher_survey_item_1) { create(:teacher_survey_item, scale: sufficient_scale_1) }
let(:sufficient_teacher_survey_item_2) { create(:teacher_survey_item, scale: sufficient_scale_1) }
let(:sufficient_teacher_survey_item_3) { create(:teacher_survey_item, scale: sufficient_scale_1) }
let(:insufficient_teacher_survey_item_4) { create(:teacher_survey_item, scale: sufficient_scale_1) }
let(:sufficient_student_survey_item_1) { create(:student_survey_item, scale: sufficient_scale_1) }
before :each do
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item_1,
academic_year:, school:, likert_score: 1)
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item_2,
academic_year:, school:, likert_score: 1)
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_1,
academic_year:, school:, likert_score: 4)
end
context 'when the average number of teacher responses per question in a subcategory is at the threshold' do
before :each do
create(:respondent, school:, academic_year:)
create(:survey, school:, academic_year:)
end
it 'returns 25 percent' do
expect(TeacherResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 25
end
end
context 'when the teacher response rate is not a whole number. eg 29.166%' do
before do
create(:respondent, school:, academic_year:)
create(:survey, school:, academic_year:)
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD + 1, survey_item: sufficient_teacher_survey_item_3,
academic_year:, school:, likert_score: 1)
end
it 'it will return the nearest whole number' do
expect(TeacherResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 29
end
end
context 'when the average number of teacher responses is greater than the total possible responses' do
before do
create(:respondent, school:, academic_year:)
create(:survey, school:, academic_year:)
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD * 11, survey_item: sufficient_teacher_survey_item_3,
academic_year:, school:, likert_score: 1)
end
it 'returns 100 percent' do
expect(TeacherResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 100
end
end
context 'when no survey information exists for that school and academic_year' do
it 'returns 100 percent' do
expect(TeacherResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 100
end
end
context 'when there is an imbalance in the response rate of the teacher items' do
context 'and one of the teacher items has no associated survey item responses' do
before do
create(:respondent, school:, academic_year:)
create(:survey, school:, academic_year:)
insufficient_teacher_survey_item_4
end
it 'ignores the empty survey item and returns only the average response rate of teacher survey items with responses' do
expect(TeacherResponseRate.new(subcategory:, school:,
academic_year:).rate).to eq 25
end
end
end
end
RSpec.describe ResponseRate, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

Loading…
Cancel
Save