feat: Update cleaner and uploader to load gender data from parent surveys

Implement graph views for parent gender data
main-eol
rebuilt 7 months ago
parent 7ebe8234cb
commit 9d8543afae

@ -3,4 +3,5 @@ class Parent < ApplicationRecord
has_many :parent_languages has_many :parent_languages
has_and_belongs_to_many :languages, join_table: :parent_languages has_and_belongs_to_many :languages, join_table: :parent_languages
has_and_belongs_to_many :races, join_table: :parent_races has_and_belongs_to_many :races, join_table: :parent_races
has_and_belongs_to_many :genders, join_table: :parent_genders
end end

@ -57,9 +57,18 @@ class SurveyItemResponse < ActiveRecord::Base
else else
race.map(&:id) race.map(&:id)
end end
SurveyItemResponse.joins("JOIN parent_races on survey_item_responses.parent_id = parent_races.parent_id JOIN parents on parents.id = parent_races.parent_id").where(
school:, academic_year:, survey_item: survey_items SurveyItemResponse.joins([parent: :races]).where(races: { id: }, survey_item: survey_items, school:, academic_year:).group(:survey_item).having("count(*) >= 10").average(:likert_score)
).where("parent_races.race_id": id).group(:survey_item).having("count(*) >= 10").average(:likert_score) }
scope :averages_for_parent_gender, lambda { |survey_items, school, academic_year, gender|
id = if gender.instance_of? ::Gender
gender.id
else
gender.map(&:id)
end
SurveyItemResponse.joins([parent: :genders]).where(genders: { id: }, survey_item: survey_items, school:, academic_year:).group(:survey_item).having("count(*) >= 10").where.not(parent: nil).average(:likert_score)
} }
scope :averages_for_language, lambda { |survey_items, school, academic_year, designations| scope :averages_for_language, lambda { |survey_items, school, academic_year, designations|

@ -0,0 +1,78 @@
# frozen_string_literal: true
module Analyze
module Graph
module Column
module Parent
class Base
def label
raise NotImplementedError
end
def basis
raise NotImplementedError
end
def show_irrelevancy_message?(construct:)
raise NotImplementedError
end
def show_insufficient_data_message?(construct:, school:, academic_years:)
raise NotImplementedError
end
def insufficiency_message
raise NotImplementedError
end
def score(construct:, school:, academic_year:)
raise NotImplementedError
end
def type
raise NotImplementedError
end
def n_size(construct:, school:, academic_year:)
raise NotImplementedError
end
def show_insufficient_data_message?(construct:, school:, academic_years:)
false
end
def basis
"parent surveys"
end
def type
:parent
end
def bubble_up_averages(construct:, averages:)
name = construct.class.name.downcase
send("#{name}_bubble_up_averages", construct:, averages:)
end
def measure_bubble_up_averages(construct:, averages:)
construct.parent_scales.map do |scale|
scale_bubble_up_averages(construct: scale, averages:)
end.remove_blanks.average
end
def scale_bubble_up_averages(construct:, averages:)
construct.survey_items.map do |survey_item|
averages[survey_item]
end.remove_blanks.average
end
def show_irrelevancy_message?(construct:)
return false if @show_irrelevancy_message == false
construct.survey_items.parent_survey_items.count.zero?
end
end
end
end
end
end

@ -0,0 +1,39 @@
# frozen_string_literal: true
module Analyze
module Graph
module Column
module Parent
class Gender < Base
attr_reader :genders, :label
def initialize(genders:, label:, show_irrelevancy_message:)
@genders = genders
@label = label
@show_irrelevancy_message = show_irrelevancy_message
end
def n_size(construct:, school:, academic_year:)
id = if genders.instance_of? ::Gender
genders.id
else
genders.map(&:id)
end
SurveyItemResponse.joins([parent: :genders]).where(genders: { id: }, survey_item: construct.parent_survey_items, school:, academic_year:).select(:parent_id).distinct.count
end
def score(construct:, school:, academic_year:)
return Score::NIL_SCORE if n_size(construct:, school:, academic_year:) < 10
averages = SurveyItemResponse.averages_for_parent_gender(construct.parent_survey_items, school, academic_year, genders)
average = bubble_up_averages(construct:, averages:).round(2)
Score.new(average:,
meets_teacher_threshold: false,
meets_student_threshold: true,
meets_admin_data_threshold: false)
end
end
end
end
end
end

@ -4,7 +4,7 @@ module Analyze
module Graph module Graph
module Column module Column
module Parent module Parent
class Language < ColumnBase class Language < Base
attr_reader :language, :label attr_reader :language, :label
def initialize(languages:, label:, show_irrelevancy_message:) def initialize(languages:, label:, show_irrelevancy_message:)
@ -13,18 +13,6 @@ module Analyze
@show_irrelevancy_message = show_irrelevancy_message @show_irrelevancy_message = show_irrelevancy_message
end end
def basis
"parent surveys"
end
def show_insufficient_data_message?(construct:, school:, academic_years:)
false
end
def type
:parent
end
def n_size(construct:, school:, academic_year:) def n_size(construct:, school:, academic_year:)
SurveyItemResponse.joins([parent: :languages]).where(languages: { designation: designations }, survey_item: construct.parent_survey_items, school:, academic_year:).select(:parent_id).distinct.count SurveyItemResponse.joins([parent: :languages]).where(languages: { designation: designations }, survey_item: construct.parent_survey_items, school:, academic_year:).select(:parent_id).distinct.count
end end
@ -44,29 +32,6 @@ module Analyze
def designations def designations
language.map(&:designation) language.map(&:designation)
end end
def bubble_up_averages(construct:, averages:)
name = construct.class.name.downcase
send("#{name}_bubble_up_averages", construct:, averages:)
end
def measure_bubble_up_averages(construct:, averages:)
construct.parent_scales.map do |scale|
scale_bubble_up_averages(construct: scale, averages:)
end.remove_blanks.average
end
def scale_bubble_up_averages(construct:, averages:)
construct.survey_items.map do |survey_item|
averages[survey_item]
end.remove_blanks.average
end
def show_irrelevancy_message?(construct:)
return false if @show_irrelevancy_message == false
construct.survey_items.parent_survey_items.count.zero?
end
end end
end end
end end

@ -4,7 +4,7 @@ module Analyze
module Graph module Graph
module Column module Column
module Parent module Parent
class Race < ColumnBase class Race < Base
attr_reader :race, :label attr_reader :race, :label
def initialize(races:, label:, show_irrelevancy_message:) def initialize(races:, label:, show_irrelevancy_message:)
@ -13,18 +13,6 @@ module Analyze
@show_irrelevancy_message = show_irrelevancy_message @show_irrelevancy_message = show_irrelevancy_message
end end
def basis
"parent surveys"
end
def show_insufficient_data_message?(construct:, school:, academic_years:)
false
end
def type
:parent
end
def n_size(construct:, school:, academic_year:) def n_size(construct:, school:, academic_year:)
designation = if race.instance_of? ::Race designation = if race.instance_of? ::Race
race.designation race.designation
@ -44,29 +32,6 @@ module Analyze
meets_student_threshold: true, meets_student_threshold: true,
meets_admin_data_threshold: false) meets_admin_data_threshold: false)
end end
def bubble_up_averages(construct:, averages:)
name = construct.class.name.downcase
send("#{name}_bubble_up_averages", construct:, averages:)
end
def measure_bubble_up_averages(construct:, averages:)
construct.parent_scales.map do |scale|
scale_bubble_up_averages(construct: scale, averages:)
end.remove_blanks.average
end
def scale_bubble_up_averages(construct:, averages:)
construct.survey_items.map do |survey_item|
averages[survey_item]
end.remove_blanks.average
end
def show_irrelevancy_message?(construct:)
return false if @show_irrelevancy_message == false
construct.survey_items.parent_survey_items.count.zero?
end
end end
end end
end end

@ -0,0 +1,42 @@
# frozen_string_literal: true
module Analyze
module Graph
class ParentsByGender
def to_s
"Parents by Gender"
end
def slug
"parents-by-gender"
end
def columns
[].tap do |array|
Gender.all.each do |gender|
label = if gender.designation.match(/\or\s/i)
[gender.designation.split("or").first.squish]
else
gender.designation.split(" ", 2).compact
end
array << Analyze::Graph::Column::Parent::Gender.new(genders: gender, label:, show_irrelevancy_message: false)
end
array << Analyze::Graph::Column::Parent::Gender.new(genders: Gender.all, label: ["All Parent"], show_irrelevancy_message: true)
end
end
def source
Analyze::Source::SurveyData.new(slices: nil, graph: self)
end
def slice
Analyze::Slice::ParentsByGroup.new(graph: self)
end
def group
Analyze::Group::Base.new(name: "Student Gender", slug: "student-gender", graph: self)
end
end
end
end

@ -166,7 +166,8 @@ module Analyze
"students-by-sped" => Analyze::Graph::StudentsBySped.new(speds: selected_speds), "students-by-sped" => Analyze::Graph::StudentsBySped.new(speds: selected_speds),
"students-by-ell" => Analyze::Graph::StudentsByEll.new(ells: selected_ells), "students-by-ell" => Analyze::Graph::StudentsByEll.new(ells: selected_ells),
"parents-by-race" => Analyze::Graph::ParentsByRace.new, "parents-by-race" => Analyze::Graph::ParentsByRace.new,
"parents-by-language" => Analyze::Graph::ParentsByLanguage.new } "parents-by-language" => Analyze::Graph::ParentsByLanguage.new,
"parents-by-gender" => Analyze::Graph::ParentsByGender.new }
end end
# The last item will per slice type will be selected as the default slice # The last item will per slice type will be selected as the default slice
@ -183,7 +184,8 @@ module Analyze
"students-by-sped" => nil, "students-by-sped" => nil,
"students-by-ell" => nil, "students-by-ell" => nil,
"parents-by-race" => Analyze::Graph::ParentsByRace.new, "parents-by-race" => Analyze::Graph::ParentsByRace.new,
"parents-by-language" => Analyze::Graph::ParentsByLanguage.new } "parents-by-language" => Analyze::Graph::ParentsByLanguage.new,
"parents-by-gender" => Analyze::Graph::ParentsByGender.new }
end end
def graphs def graphs

@ -79,7 +79,7 @@ class Cleaner
headers = headers.to_set headers = headers.to_set
headers = headers.merge(Set.new(["Raw Income", "Income", "Raw ELL", "ELL", "Raw SpEd", "SpEd", "Progress Count", headers = headers.merge(Set.new(["Raw Income", "Income", "Raw ELL", "ELL", "Raw SpEd", "SpEd", "Progress Count",
"Race", "Gender", "Raw Housing Status", "Housing Status", "Home Language", "Home Languages", "Declared Races of Children from Parents"])).to_a "Race", "Gender", "Raw Housing Status", "Housing Status", "Home Language", "Home Languages", "Declared Races of Children from Parents", "Declared Genders of Children from Parents"])).to_a
filtered_headers = include_all_headers(headers:) filtered_headers = include_all_headers(headers:)
filtered_headers = remove_unwanted_headers(headers: filtered_headers) filtered_headers = remove_unwanted_headers(headers: filtered_headers)
log_headers = (filtered_headers + ["Valid Duration?", "Valid Progress?", "Valid Grade?", log_headers = (filtered_headers + ["Valid Duration?", "Valid Progress?", "Valid Grade?",

@ -31,6 +31,7 @@ class SurveyItemValues
row["Housing Status"] = housing row["Housing Status"] = housing
row["Home Languages"] = languages.join(",") row["Home Languages"] = languages.join(",")
row["Declared Races of Children from Parents"] = races_of_children.join(",") row["Declared Races of Children from Parents"] = races_of_children.join(",")
row["Declared Genders of Children from Parents"] = genders_of_children.join(",")
end end
def normalize_headers(headers:) def normalize_headers(headers:)
@ -146,6 +147,25 @@ class SurveyItemValues
end end
end end
def genders_of_children
@genders_of_children ||= [].tap do |gender_codes|
matches = headers.select do |header|
# Explanation:
# ^: Start of the string.
# (?!.*text): Negative lookahead — ensures that the word text does not appear anywhere in the string.
# .*?: Lazily match any characters (to get to the word gender).
# gender: Match the word gender
header.match(/^(?!.*text).*?gender/i)
end
matches.each do |match|
code = row[match]&.strip
gender_codes << Gender.qualtrics_code_from(code).to_i unless code.nil?
end
gender_codes << 99 if gender_codes.empty?
end.uniq.sort
end
def races def races
@races ||= begin @races ||= begin
race_codes ||= self_report = value_from(pattern: /Race\s*self\s*report/i) race_codes ||= self_report = value_from(pattern: /Race\s*self\s*report/i)

@ -118,6 +118,10 @@ class SurveyResponsesDataLoader
tmp_races = row.races_of_children.map { |race| races[race] }.reject(&:nil?) tmp_races = row.races_of_children.map { |race| races[race] }.reject(&:nil?)
parent.races.concat(tmp_races) parent.races.concat(tmp_races)
parent.genders.delete_all
tmp_genders = row.genders_of_children.map { |race| genders[race] }.reject(&:nil?)
parent.genders.concat(tmp_genders)
parent.housing = housings[row.housing] if row.housing.present? parent.housing = housings[row.housing] if row.housing.present?
parent.save parent.save
end end

@ -0,0 +1,10 @@
class CreateParentGenders < ActiveRecord::Migration[8.0]
def change
create_table :parent_genders do |t|
t.references :parent, null: false, foreign_key: true
t.references :gender, null: false, foreign_key: true
t.timestamps
end
end
end

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_05_15_205734) do ActiveRecord::Schema[8.0].define(version: 2025_05_23_222834) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql" enable_extension "pg_catalog.plpgsql"
@ -330,6 +330,15 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_15_205734) do
t.index ["subcategory_id"], name: "index_measures_on_subcategory_id" t.index ["subcategory_id"], name: "index_measures_on_subcategory_id"
end end
create_table "parent_genders", force: :cascade do |t|
t.bigint "parent_id", null: false
t.bigint "gender_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["gender_id"], name: "index_parent_genders_on_gender_id"
t.index ["parent_id"], name: "index_parent_genders_on_parent_id"
end
create_table "parent_languages", force: :cascade do |t| create_table "parent_languages", force: :cascade do |t|
t.bigint "parent_id", null: false t.bigint "parent_id", null: false
t.bigint "language_id", null: false t.bigint "language_id", null: false
@ -543,6 +552,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_15_205734) do
add_foreign_key "legacy_school_categories", "legacy_categories", column: "category_id" add_foreign_key "legacy_school_categories", "legacy_categories", column: "category_id"
add_foreign_key "legacy_school_categories", "legacy_schools", column: "school_id" add_foreign_key "legacy_school_categories", "legacy_schools", column: "school_id"
add_foreign_key "measures", "subcategories" add_foreign_key "measures", "subcategories"
add_foreign_key "parent_genders", "genders"
add_foreign_key "parent_genders", "parents"
add_foreign_key "parent_languages", "languages" add_foreign_key "parent_languages", "languages"
add_foreign_key "parent_languages", "parents" add_foreign_key "parent_languages", "parents"
add_foreign_key "parent_races", "parents" add_foreign_key "parent_races", "parents"

@ -1,9 +1,9 @@
StartDate,EndDate,Status,IPAddress,Progress,Duration (in seconds),Finished,RecordedDate,ResponseId,DistributionChannel,UserLanguage,DESE ID,Number of Children,Gender-1,Gender-1_7_TEXT,Race-1,Race-1_7_TEXT,Gender-2,Gender-2_7_TEXT,Race-2,Race-2_7_TEXT,Gender-3,Gender-3_7_TEXT,Race-3,Race-3_7_TEXT,Gender-4,Gender-4_7_TEXT,Race-4,Race-4_7_TEXT,Gender-5,Gender-5_7_TEXT,Race-5,Race-5_7_TEXT,Gender,Gender_7_TEXT,p-scrp-q3,p-scrp-q2,p-valm-q1,p-valm-q2,p-valm-q3,p-valm-q4,p-comm-q1,p-comm-q2,p-comm-q3,p-tcom-q1,P-tcom-q2,p-tcom-q3,p-evnt-q4,p-comm-q4,p-evnt-q3,p-evnt-q1,p-evnt-q2,p-socx-q3,p-socx-q4,p-scrp-q1,p-socx-q1,p-sosu-q1,p-sosu-q2,p-sosu-q3,p-socx-q2,p-sosu-q4,p-phys-q3,p-acpr-q1,p-acpr-q2,p-acpr-q3,p-acpr-q4,p-cure-q1,p-cure-q2,p-cure-q3,p-cure-q4,Housing,Housing_100_TEXT,Employment,Employment_100_TEXT,Caregivers,Caregivers_100_TEXT,Education,Education_100_TEXT,Benefits,Benefits_100_TEXT,Language,Language_100_TEXT,Raw Income,Income,Raw ELL,ELL,Raw SpEd,SpEd,Progress Count StartDate,EndDate,Status,IPAddress,Progress,Duration (in seconds),Finished,RecordedDate,ResponseId,DistributionChannel,UserLanguage,DESE ID,Number of Children,Gender-1,Gender-1_7_TEXT,Race-1,Race-1_7_TEXT,Gender-2,Gender-2_7_TEXT,Race-2,Race-2_7_TEXT,Gender-3,Gender-3_7_TEXT,Race-3,Race-3_7_TEXT,Gender-4,Gender-4_7_TEXT,Race-4,Race-4_7_TEXT,Gender-5,Gender-5_7_TEXT,Race-5,Race-5_7_TEXT,Gender,Gender_7_TEXT,p-scrp-q3,p-scrp-q2,p-valm-q1,p-valm-q2,p-valm-q3,p-valm-q4,p-comm-q1,p-comm-q2,p-comm-q3,p-tcom-q1,P-tcom-q2,p-tcom-q3,p-evnt-q4,p-comm-q4,p-evnt-q3,p-evnt-q1,p-evnt-q2,p-socx-q3,p-socx-q4,p-scrp-q1,p-socx-q1,p-sosu-q1,p-sosu-q2,p-sosu-q3,p-socx-q2,p-sosu-q4,p-phys-q3,p-acpr-q1,p-acpr-q2,p-acpr-q3,p-acpr-q4,p-cure-q1,p-cure-q2,p-cure-q3,p-cure-q4,Housing,Housing_100_TEXT,Employment,Employment_100_TEXT,Caregivers,Caregivers_100_TEXT,Education,Education_100_TEXT,Benefits,Benefits_100_TEXT,Language,Language_100_TEXT,Raw Income,Income,Raw ELL,ELL,Raw SpEd,SpEd,Progress Count
5/1/2024 10:04:34,5/1/2024 10:10:49,0,72.93.86.98,100,374,1,2021-03-31T10:01:36,parent_survey_response_1,email,EN,1500025,1,,,1,,,,,,,,,,,,,,,,,,2,,4,5,5,4,5,5,5,5,5,4,4,5,4,5,3,4,5,4,4,5,5,5,5,5,5,5,1,2,2,2,1,4,5,5,5,1,,1,,2,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34 5/1/2024 10:04:34,5/1/2024 10:10:49,0,72.93.86.98,100,374,1,2021-03-31T10:01:36,parent_survey_response_1,email,EN,1500025,1,,,1,,,,,,,,,,,,,,,,,,2,,4,5,5,4,5,5,5,5,5,4,4,5,4,5,3,4,5,4,4,5,5,5,5,5,5,5,1,2,2,2,1,4,5,5,5,1,,1,,2,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34
5/1/2024 10:03:52,5/1/2024 10:14:42,0,73.69.182.58,100,649,1,2021-04-01T10:01:36,parent_survey_response_2,email,EN,1500025,1,,,,,,,,,,,6,,,,7,,,,,,1,,4,4,5,5,5,5,5,5,5,5,5,5,3,5,4,5,5,5,5,5,4,4,4,4,5,5,1,5,4,5,5,5,5,5,5,1,,99,,2,,3,,1,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34 5/1/2024 10:03:52,5/1/2024 10:14:42,0,73.69.182.58,100,649,1,2021-04-01T10:01:36,parent_survey_response_2,email,EN,1500025,1,,,,,,,,,,,6,,,,7,,,,,,1,,4,4,5,5,5,5,5,5,5,5,5,5,3,5,4,5,5,5,5,5,4,4,4,4,5,5,1,5,4,5,5,5,5,5,5,1,,99,,2,,3,,1,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34
5/1/2024 10:06:44,5/1/2024 10:15:41,0,50.235.109.170,100,537,1,2021-04-02T10:01:36,parent_survey_response_3,email,EN,1500025,2,2,,4,,2,,"1,5",,,,,,,,,,,,,,2,,5,5,5,4,5,5,5,5,5,4,4,5,4,4,3,4,4,4,4,5,4,4,5,5,2,5,3,4,4,4,4,5,5,5,5,1,,1,,3,,6,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34 5/1/2024 10:06:44,5/1/2024 10:15:41,0,50.235.109.170,100,537,1,2021-04-02T10:01:36,parent_survey_response_3,email,EN,1500025,2,1,,4,,2,,"1,5",,,,,,,,,,,,,,2,,5,5,5,4,5,5,5,5,5,4,4,5,4,4,3,4,4,4,4,5,4,4,5,5,2,5,3,4,4,4,4,5,5,5,5,1,,1,,3,,6,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34
5/1/2024 10:14:23,5/1/2024 10:22:22,0,73.38.238.192,100,478,1,2021-04-03T10:01:36,parent_survey_response_4,email,EN,1500025,1,,,,,,,,,,,,,,,,,,,,,1,,5,5,5,5,5,5,5,4,5,4,4,4,2,5,4,5,4,5,5,5,3,5,5,5,2,5,1,5,5,5,5,5,5,5,5,1,,1,,2,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34 5/1/2024 10:14:23,5/1/2024 10:22:22,0,73.38.238.192,100,478,1,2021-04-03T10:01:36,parent_survey_response_4,email,EN,1500025,1,3,,7,,,,,,,,,,,,,,,,,,4,,5,5,5,5,5,5,5,4,5,4,4,4,2,5,4,5,4,5,5,5,3,5,5,5,2,5,1,5,5,5,5,5,5,5,5,1,,1,,2,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34
5/1/2024 10:18:39,5/1/2024 10:23:49,0,73.69.158.255,100,310,1,2021-04-04T10:01:36,parent_survey_response_5,email,EN,1500025,2,2,,"1,2,3",,1,,"4,5,8",,,,,,,,,,,,,,2,,5,4,5,5,5,5,1,1,1,1,1,1,3,1,4,4,5,1,1,1,4,1,1,1,4,5,1,5,5,5,5,1,5,1,1,1,,"2,4",,3,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34 5/1/2024 10:18:39,5/1/2024 10:23:49,0,73.69.158.255,100,310,1,2021-04-04T10:01:36,parent_survey_response_5,email,EN,1500025,2,2,,"1,2,3",,,,"4,5,8",,,,,,,,,,,,,,2,,5,4,5,5,5,5,1,1,1,1,1,1,3,1,4,4,5,1,1,1,4,1,1,1,4,5,1,5,5,5,5,1,5,1,1,1,,"2,4",,3,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34
5/1/2024 10:20:30,5/1/2024 10:25:16,0,73.182.146.201,100,285,1,2021-04-05T10:01:36,parent_survey_response_6,email,EN,1500025,1,,,,,,,,,,,,,,,1,,,,"2,3,4,5,8",,1,,3,3,3,1,3,2,4,2,4,1,1,3,3,4,3,4,1,5,5,4,3,5,4,3,3,1,3,5,5,4,5,4,4,5,4,2,,2,,2,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34 5/1/2024 10:20:30,5/1/2024 10:25:16,0,73.182.146.201,100,285,1,2021-04-05T10:01:36,parent_survey_response_6,email,EN,1500025,1,,,,,,,,,,,,,,,1,,,,"2,3,4,5,8",,,,3,3,3,1,3,2,4,2,4,1,1,3,3,4,3,4,1,5,5,4,3,5,4,3,3,1,3,5,5,4,5,4,4,5,4,2,,2,,2,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34
5/1/2024 10:14:01,5/1/2024 10:27:19,0,209.107.182.203,100,798,1,2021-04-06T10:01:36,parent_survey_response_7,email,EN,1500025,2,1,,5,,1,,5,,,,,,,,,,,,,,1,,3,3,3,1,3,2,4,2,4,1,1,3,3,4,3,4,1,5,5,4,3,5,4,3,3,1,3,5,5,4,5,4,4,5,4,1,,1,,2,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34 5/1/2024 10:14:01,5/1/2024 10:27:19,0,209.107.182.203,100,798,1,2021-04-06T10:01:36,parent_survey_response_7,email,EN,1500025,2,6,,5,,,,5,,,,,,,,,,,,,,,,3,3,3,1,3,2,4,2,4,1,1,3,3,4,3,4,1,5,5,4,3,5,4,3,3,1,3,5,5,4,5,4,4,5,4,1,,1,,2,,5,,2,,1,,,Economically Disadvantaged - N,,Not ELL,,Not Special Education,34
5/1/2024 10:14:01,5/1/2024 10:27:19,0,209.107.182.203,100,798,1,2021-04-06T10:01:36,parent_survey_response_8,email,EN,1500025,2,1,,5,,1,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 5/1/2024 10:14:01,5/1/2024 10:27:19,0,209.107.182.203,100,798,1,2021-04-06T10:01:36,parent_survey_response_8,email,EN,1500025,2,Prefer not to disclose,,5,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

1 StartDate EndDate Status IPAddress Progress Duration (in seconds) Finished RecordedDate ResponseId DistributionChannel UserLanguage DESE ID Number of Children Gender-1 Gender-1_7_TEXT Race-1 Race-1_7_TEXT Gender-2 Gender-2_7_TEXT Race-2 Race-2_7_TEXT Gender-3 Gender-3_7_TEXT Race-3 Race-3_7_TEXT Gender-4 Gender-4_7_TEXT Race-4 Race-4_7_TEXT Gender-5 Gender-5_7_TEXT Race-5 Race-5_7_TEXT Gender Gender_7_TEXT p-scrp-q3 p-scrp-q2 p-valm-q1 p-valm-q2 p-valm-q3 p-valm-q4 p-comm-q1 p-comm-q2 p-comm-q3 p-tcom-q1 P-tcom-q2 p-tcom-q3 p-evnt-q4 p-comm-q4 p-evnt-q3 p-evnt-q1 p-evnt-q2 p-socx-q3 p-socx-q4 p-scrp-q1 p-socx-q1 p-sosu-q1 p-sosu-q2 p-sosu-q3 p-socx-q2 p-sosu-q4 p-phys-q3 p-acpr-q1 p-acpr-q2 p-acpr-q3 p-acpr-q4 p-cure-q1 p-cure-q2 p-cure-q3 p-cure-q4 Housing Housing_100_TEXT Employment Employment_100_TEXT Caregivers Caregivers_100_TEXT Education Education_100_TEXT Benefits Benefits_100_TEXT Language Language_100_TEXT Raw Income Income Raw ELL ELL Raw SpEd SpEd Progress Count
2 5/1/2024 10:04:34 5/1/2024 10:10:49 0 72.93.86.98 100 374 1 2021-03-31T10:01:36 parent_survey_response_1 email EN 1500025 1 1 2 4 5 5 4 5 5 5 5 5 4 4 5 4 5 3 4 5 4 4 5 5 5 5 5 5 5 1 2 2 2 1 4 5 5 5 1 1 2 5 2 1 Economically Disadvantaged - N Not ELL Not Special Education 34
3 5/1/2024 10:03:52 5/1/2024 10:14:42 0 73.69.182.58 100 649 1 2021-04-01T10:01:36 parent_survey_response_2 email EN 1500025 1 6 7 1 4 4 5 5 5 5 5 5 5 5 5 5 3 5 4 5 5 5 5 5 4 4 4 4 5 5 1 5 4 5 5 5 5 5 5 1 99 2 3 1 1 Economically Disadvantaged - N Not ELL Not Special Education 34
4 5/1/2024 10:06:44 5/1/2024 10:15:41 0 50.235.109.170 100 537 1 2021-04-02T10:01:36 parent_survey_response_3 email EN 1500025 2 2 1 4 2 1,5 2 5 5 5 4 5 5 5 5 5 4 4 5 4 4 3 4 4 4 4 5 4 4 5 5 2 5 3 4 4 4 4 5 5 5 5 1 1 3 6 2 1 Economically Disadvantaged - N Not ELL Not Special Education 34
5 5/1/2024 10:14:23 5/1/2024 10:22:22 0 73.38.238.192 100 478 1 2021-04-03T10:01:36 parent_survey_response_4 email EN 1500025 1 3 7 1 4 5 5 5 5 5 5 5 4 5 4 4 4 2 5 4 5 4 5 5 5 3 5 5 5 2 5 1 5 5 5 5 5 5 5 5 1 1 2 5 2 1 Economically Disadvantaged - N Not ELL Not Special Education 34
6 5/1/2024 10:18:39 5/1/2024 10:23:49 0 73.69.158.255 100 310 1 2021-04-04T10:01:36 parent_survey_response_5 email EN 1500025 2 2 1,2,3 1 4,5,8 2 5 4 5 5 5 5 1 1 1 1 1 1 3 1 4 4 5 1 1 1 4 1 1 1 4 5 1 5 5 5 5 1 5 1 1 1 2,4 3 5 2 1 Economically Disadvantaged - N Not ELL Not Special Education 34
7 5/1/2024 10:20:30 5/1/2024 10:25:16 0 73.182.146.201 100 285 1 2021-04-05T10:01:36 parent_survey_response_6 email EN 1500025 1 1 2,3,4,5,8 1 3 3 3 1 3 2 4 2 4 1 1 3 3 4 3 4 1 5 5 4 3 5 4 3 3 1 3 5 5 4 5 4 4 5 4 2 2 2 5 2 1 Economically Disadvantaged - N Not ELL Not Special Education 34
8 5/1/2024 10:14:01 5/1/2024 10:27:19 0 209.107.182.203 100 798 1 2021-04-06T10:01:36 parent_survey_response_7 email EN 1500025 2 1 6 5 1 5 1 3 3 3 1 3 2 4 2 4 1 1 3 3 4 3 4 1 5 5 4 3 5 4 3 3 1 3 5 5 4 5 4 4 5 4 1 1 2 5 2 1 Economically Disadvantaged - N Not ELL Not Special Education 34
9 5/1/2024 10:14:01 5/1/2024 10:27:19 0 209.107.182.203 100 798 1 2021-04-06T10:01:36 parent_survey_response_8 email EN 1500025 2 1 Prefer not to disclose 5 1 5

@ -315,7 +315,7 @@ def reads_headers_from_raw_csv(processed_data)
"s-grit-q1", "s-grit-q2", "s-grit-q3", "s-grit-q4", "s-expa-q1", "s-poaf-q1", "s-poaf-q2", "s-poaf-q3", "s-grit-q1", "s-grit-q2", "s-grit-q3", "s-grit-q4", "s-expa-q1", "s-poaf-q1", "s-poaf-q2", "s-poaf-q3",
"s-poaf-q4", "s-tint-q1-1", "s-tint-q2-1", "s-tint-q3-1", "s-tint-q4-1", "s-tint-q5-1", "s-acpr-q1-1", "s-poaf-q4", "s-tint-q1-1", "s-tint-q2-1", "s-tint-q3-1", "s-tint-q4-1", "s-tint-q5-1", "s-acpr-q1-1",
"s-acpr-q2-1", "s-acpr-q3-1", "s-acpr-q4-1", "s-peff-q1-1", "s-peff-q2-1", "s-peff-q3-1", "s-peff-q4-1", "s-acpr-q2-1", "s-acpr-q3-1", "s-acpr-q4-1", "s-peff-q1-1", "s-peff-q2-1", "s-peff-q3-1", "s-peff-q4-1",
"s-peff-q5-1", "s-peff-q6-1", "Raw Income", "Income", "Raw ELL", "ELL", "Raw SpEd", "SpEd", "Progress Count", "Housing Status", "Raw Housing Status", "Home Language", "Home Languages", "Declared Races of Children from Parents"].to_set.sort "s-peff-q5-1", "s-peff-q6-1", "Raw Income", "Income", "Raw ELL", "ELL", "Raw SpEd", "SpEd", "Progress Count", "Housing Status", "Raw Housing Status", "Home Language", "Home Languages", "Declared Races of Children from Parents", "Declared Genders of Children from Parents"].to_set.sort
end end
def invalid_rows_are_rejected_for_the_correct_reasons(data) def invalid_rows_are_rejected_for_the_correct_reasons(data)

@ -129,12 +129,12 @@ describe SurveyResponsesDataLoader do
let(:unknown_race) { create(:race, qualtrics_code: 99, designation: "Race/Ethnicity Not Listed") } let(:unknown_race) { create(:race, qualtrics_code: 99, designation: "Race/Ethnicity Not Listed") }
let(:multiracial) { create(:race, qualtrics_code: 100, designation: "Multiracial") } let(:multiracial) { create(:race, qualtrics_code: 100, designation: "Multiracial") }
let(:languages){ let(:languages) do
create(:language, designation: "English") create(:language, designation: "English")
create(:language, designation: "Spanish") create(:language, designation: "Spanish")
create(:language, designation: "Portuguese") create(:language, designation: "Portuguese")
create(:language, designation: "Unknown") create(:language, designation: "Unknown")
} end
let(:setup) do let(:setup) do
ay_2020_21 ay_2020_21
@ -277,6 +277,10 @@ describe SurveyResponsesDataLoader do
it "loads the correct set of races for parents" do it "loads the correct set of races for parents" do
assigns_races_to_parents assigns_races_to_parents
end end
it "loads the correct set of genders for parents" do
assigns_genders_to_parents
end
end end
end end
@ -470,7 +474,6 @@ def assigns_races_to_students
end end
end end
def assigns_races_to_parents def assigns_races_to_parents
results = { results = {
"parent_survey_response_1" => [american_indian], "parent_survey_response_1" => [american_indian],
@ -481,7 +484,8 @@ def assigns_races_to_parents
multiracial], multiracial],
"parent_survey_response_6" => [american_indian, asian, black, latinx, white, middle_eastern, "parent_survey_response_6" => [american_indian, asian, black, latinx, white, middle_eastern,
multiracial], multiracial],
"parent_survey_response_7" => [white] } "parent_survey_response_7" => [white]
}
results.each do |key, value| results.each do |key, value|
race = SurveyItemResponse.find_by_response_id(key).parent.races.to_a race = SurveyItemResponse.find_by_response_id(key).parent.races.to_a
@ -489,3 +493,17 @@ def assigns_races_to_parents
expect(race).to eq value expect(race).to eq value
end end
end end
def assigns_genders_to_parents
results = { "parent_survey_response_1" => [male],
"parent_survey_response_2" => [female],
"parent_survey_response_3" => [female, male],
"parent_survey_response_4" => [non_binary],
"parent_survey_response_5" => [male],
"parent_survey_response_6" => [unknown_gender] }
# "parent_survey_response_7" => [non_binary] }
results.each do |key, value|
expect(SurveyItemResponse.where(response_id: key).first.parent.genders).to eq value
end
end

Loading…
Cancel
Save