mirror of
https://github.com/edcommonwealth/sqm-dashboards.git
synced 2026-03-07 21:48:16 -08:00
feat: create a parents by language graph
Update demographics table with lanugage options Create a lanugage table to hold the new languages Update the demographic loader to input languages into the database Update the cleaner to read the language column Update the parent table to hold a reference to a language Update the data uploader script to read the language from the csv and update the language information for any parent items that already exist (or create database entries if none already exist) update the analyze interface to add controls for selecting ‘parents by group’ and a dropdown for ‘parent by language’ Update the analyze controller to read the parent-by-group parameter Create a graph for the parent-by-group view Bubble up averages for language calculations. Make sure n-size only counts responses for a given measure.
This commit is contained in:
parent
bedab713af
commit
0f457becf0
31 changed files with 413 additions and 109 deletions
|
|
@ -1,4 +1,7 @@
|
||||||
class Housing < ApplicationRecord
|
class Housing < ApplicationRecord
|
||||||
|
has_many :parents, dependent: :nullify
|
||||||
|
scope :by_designation, -> { all.map { |housing| [housing.designation, housing] }.to_h }
|
||||||
|
|
||||||
def self.to_designation(housing)
|
def self.to_designation(housing)
|
||||||
return "Unknown" if housing.blank?
|
return "Unknown" if housing.blank?
|
||||||
|
|
||||||
|
|
|
||||||
33
app/models/language.rb
Normal file
33
app/models/language.rb
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
class Language < ApplicationRecord
|
||||||
|
scope :by_designation, -> { all.map { |language| [language.designation, language] }.to_h }
|
||||||
|
has_many :parent_languages, dependent: :destroy
|
||||||
|
has_many :parents, through: :parent_languages, dependent: :nullify
|
||||||
|
|
||||||
|
include FriendlyId
|
||||||
|
|
||||||
|
friendly_id :designation, use: [:slugged]
|
||||||
|
def self.to_designation(language)
|
||||||
|
return "Prefer not to disclose" if language.blank?
|
||||||
|
|
||||||
|
case language
|
||||||
|
in /^1$/i
|
||||||
|
"English"
|
||||||
|
in /^2$/i
|
||||||
|
"Portuguese"
|
||||||
|
in /^3$/i
|
||||||
|
"Spanish"
|
||||||
|
in /^99$/i
|
||||||
|
"Prefer not to disclose"
|
||||||
|
in /|^100$/i
|
||||||
|
"Prefer to self-describe"
|
||||||
|
else
|
||||||
|
puts "************************************"
|
||||||
|
puts "******** ERROR **********"
|
||||||
|
puts ""
|
||||||
|
puts "Error parsing Language column. '#{language}' is not a known value. Halting execution"
|
||||||
|
puts ""
|
||||||
|
puts "************************************"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -51,6 +51,10 @@ class Measure < ActiveRecord::Base
|
||||||
@student_scales ||= scales.student_scales
|
@student_scales ||= scales.student_scales
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parent_scales
|
||||||
|
@parent_scales ||= scales.parent_scales
|
||||||
|
end
|
||||||
|
|
||||||
def includes_teacher_survey_items?
|
def includes_teacher_survey_items?
|
||||||
@includes_teacher_survey_items ||= teacher_survey_items.length.positive?
|
@includes_teacher_survey_items ||= teacher_survey_items.length.positive?
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,5 @@
|
||||||
class Parent < ApplicationRecord
|
class Parent < ApplicationRecord
|
||||||
|
belongs_to :housing, optional: true
|
||||||
|
has_many :parent_languages
|
||||||
|
has_and_belongs_to_many :languages, join_table: :parent_languages
|
||||||
end
|
end
|
||||||
|
|
|
||||||
4
app/models/parent_language.rb
Normal file
4
app/models/parent_language.rb
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
class ParentLanguage < ApplicationRecord
|
||||||
|
belongs_to :parent
|
||||||
|
belongs_to :language
|
||||||
|
end
|
||||||
|
|
@ -21,15 +21,11 @@ module Report
|
||||||
Thread.new do
|
Thread.new do
|
||||||
while measure = jobs.pop(true)
|
while measure = jobs.pop(true)
|
||||||
academic_years.each do |academic_year|
|
academic_years.each do |academic_year|
|
||||||
all_grades = Set.new
|
|
||||||
|
|
||||||
respondents = Respondent.where(school: schools, academic_year:)
|
respondents = Respondent.where(school: schools, academic_year:)
|
||||||
respondents.each do |respondent|
|
|
||||||
respondent.enrollment_by_grade.keys.each do |grade|
|
enrollment = respondents.map do | respondent| respondent.enrollment_by_grade.keys end.flatten.compact.uniq.sort
|
||||||
all_grades.add(grade)
|
grades_with_responses = ::SurveyItemResponse.where(school: schools, academic_year:).where.not(grade: nil).pluck(:grade).uniq.sort
|
||||||
end
|
all_grades = (enrollment & grades_with_responses).sort
|
||||||
end
|
|
||||||
all_grades = all_grades.to_a
|
|
||||||
grades = "#{all_grades.first}-#{all_grades.last}"
|
grades = "#{all_grades.first}-#{all_grades.last}"
|
||||||
|
|
||||||
begin_date = ::SurveyItemResponse.where(school: schools,
|
begin_date = ::SurveyItemResponse.where(school: schools,
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ class Sped < ApplicationRecord
|
||||||
case sped
|
case sped
|
||||||
in /active|^A$|1|^Special\s*Education$/i
|
in /active|^A$|1|^Special\s*Education$/i
|
||||||
"Special Education"
|
"Special Education"
|
||||||
in %r{^I$|exited|0|^Not\s*Special\s*Education$|Does\s*not\s*apply|Referred|Ineligible|^No\s*special\s*needs$|Not\s*SPED|^#*N/*A$}i
|
in /^I$|exited|0|^Not\s*Special\s*Education$|Does\s*not\s*apply|Referred|Ineligible|^No\s*special\s*needs$|Not\s*SPED/i
|
||||||
"Not Special Education"
|
"Not Special Education"
|
||||||
in /^Unknown|^SpecialEdStatus|^SPED/i
|
in %r{^#*N/*A$|^Unknown|^SpecialEdStatus|^SPED}i
|
||||||
"Unknown"
|
"Unknown"
|
||||||
else
|
else
|
||||||
puts "************************************"
|
puts "************************************"
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ class SurveyItemResponse < ActiveRecord::Base
|
||||||
).where("student_races.race_id": race.id).group(:survey_item).having("count(*) >= 10").average(:likert_score)
|
).where("student_races.race_id": race.id).group(:survey_item).having("count(*) >= 10").average(:likert_score)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope :averages_for_language, lambda { |survey_items, school, academic_year, designations|
|
||||||
|
SurveyItemResponse.joins([parent: :languages]).where(languages: { designation: designations }, survey_item: survey_items, school:, academic_year:).group(:survey_item).average(:likert_score)
|
||||||
|
}
|
||||||
|
|
||||||
def self.grouped_responses(school:, academic_year:)
|
def self.grouped_responses(school:, academic_year:)
|
||||||
@grouped_responses ||= Hash.new do |memo, (school, academic_year)|
|
@grouped_responses ||= Hash.new do |memo, (school, academic_year)|
|
||||||
memo[[school, academic_year]] =
|
memo[[school, academic_year]] =
|
||||||
|
|
|
||||||
60
app/presenters/analyze/graph/column/language.rb
Normal file
60
app/presenters/analyze/graph/column/language.rb
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
class Language < ColumnBase
|
||||||
|
attr_reader :language, :label
|
||||||
|
|
||||||
|
def initialize(languages:, label:)
|
||||||
|
@language = languages
|
||||||
|
@label = label
|
||||||
|
end
|
||||||
|
|
||||||
|
def basis
|
||||||
|
"parent surveys"
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_irrelevancy_message?(measure:)
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_insufficient_data_message?(measure:, school:, academic_years:)
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def type
|
||||||
|
:parent
|
||||||
|
end
|
||||||
|
|
||||||
|
def n_size(measure:, school:, academic_year:)
|
||||||
|
SurveyItemResponse.joins([parent: :languages]).where(languages: { designation: designations }, survey_item: measure.parent_survey_items, school:, academic_year:).select(:parent_id).distinct.count
|
||||||
|
end
|
||||||
|
|
||||||
|
def score(measure:, school:, academic_year:)
|
||||||
|
return Score::NIL_SCORE if n_size(measure:, school:, academic_year:) < 10
|
||||||
|
|
||||||
|
averages = SurveyItemResponse.averages_for_language(measure.parent_survey_items, school, academic_year,
|
||||||
|
designations)
|
||||||
|
average = bubble_up_averages(measure:, averages:).round(2)
|
||||||
|
Score.new(average:,
|
||||||
|
meets_teacher_threshold: false,
|
||||||
|
meets_student_threshold: true,
|
||||||
|
meets_admin_data_threshold: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def designations
|
||||||
|
language.map(&:designation)
|
||||||
|
end
|
||||||
|
|
||||||
|
def bubble_up_averages(measure:, averages:)
|
||||||
|
measure.parent_scales.map do |scale|
|
||||||
|
scale.survey_items.map do |survey_item|
|
||||||
|
averages[survey_item]
|
||||||
|
end.remove_blanks.average
|
||||||
|
end.remove_blanks.average
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
43
app/presenters/analyze/graph/parents_by_language.rb
Normal file
43
app/presenters/analyze/graph/parents_by_language.rb
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
class ParentsByLanguage
|
||||||
|
attr_reader :speds
|
||||||
|
|
||||||
|
ALL_LANGUAGES = Language.all
|
||||||
|
ENGLISH_LANGUAGES = ALL_LANGUAGES.select { |language| language.designation == "English" }
|
||||||
|
UNKNOWN_LANGUAGES = ALL_LANGUAGES.select { |language| language.designation == "Prefer not to disclose" }
|
||||||
|
NON_ENGLISH_LANGUAGES = (ALL_LANGUAGES - ENGLISH_LANGUAGES - UNKNOWN_LANGUAGES)
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"Parents by Language"
|
||||||
|
end
|
||||||
|
|
||||||
|
def slug
|
||||||
|
"parents-by-language"
|
||||||
|
end
|
||||||
|
|
||||||
|
def columns
|
||||||
|
[].tap do |array|
|
||||||
|
array << Analyze::Graph::Column::Language.new(languages: ENGLISH_LANGUAGES, label: ["English", "Speaking"])
|
||||||
|
array << Analyze::Graph::Column::Language.new(languages: NON_ENGLISH_LANGUAGES, label: ["Non English", "Speaking"])
|
||||||
|
array << Analyze::Graph::Column::Language.new(languages: UNKNOWN_LANGUAGES, label: ["Unknown"])
|
||||||
|
array << Analyze::Graph::Column::Language.new(languages: ALL_LANGUAGES, label: ["All", "Parents"])
|
||||||
|
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: "Language", slug: "language", graph: self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -96,10 +96,14 @@ module Analyze
|
||||||
end
|
end
|
||||||
|
|
||||||
def groups
|
def groups
|
||||||
@groups = graphs.map(&:group)
|
@groups ||=
|
||||||
.reject { |group| group.name.nil? }
|
begin
|
||||||
.sort_by { |group| group.name }
|
first_char_of_class_name = graph.class.name.demodulize.first
|
||||||
.uniq
|
graphs.select { |graph| graph.class.name.demodulize.first == first_char_of_class_name }.map(&:group)
|
||||||
|
.reject { |group| group.name.nil? }
|
||||||
|
.sort_by { |group| group.name }
|
||||||
|
.uniq
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def group
|
def group
|
||||||
|
|
@ -159,7 +163,8 @@ module Analyze
|
||||||
Analyze::Graph::StudentsByGender.new(genders: selected_genders),
|
Analyze::Graph::StudentsByGender.new(genders: selected_genders),
|
||||||
Analyze::Graph::StudentsByIncome.new(incomes: selected_incomes),
|
Analyze::Graph::StudentsByIncome.new(incomes: selected_incomes),
|
||||||
Analyze::Graph::StudentsBySped.new(speds: selected_speds),
|
Analyze::Graph::StudentsBySped.new(speds: selected_speds),
|
||||||
Analyze::Graph::StudentsByEll.new(ells: selected_ells)]
|
Analyze::Graph::StudentsByEll.new(ells: selected_ells),
|
||||||
|
Analyze::Graph::ParentsByLanguage.new]
|
||||||
end
|
end
|
||||||
|
|
||||||
def graph
|
def graph
|
||||||
|
|
|
||||||
9
app/presenters/analyze/slice/parents_by_group.rb
Normal file
9
app/presenters/analyze/slice/parents_by_group.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
module Analyze
|
||||||
|
module Slice
|
||||||
|
class ParentsByGroup < Base
|
||||||
|
def initialize(graph:, label: "Parents by Group", slug: "parents-by-group")
|
||||||
|
super(label:, slug:, graph:)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -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"])).to_a
|
"Race", "Gender", "Raw Housing Status", "Housing Status", "Home Language", "Home Languages"])).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?",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ class DemographicLoader
|
||||||
create_from_column(column: "ELL", row:, model: Ell)
|
create_from_column(column: "ELL", row:, model: Ell)
|
||||||
create_from_column(column: "Special Ed Status", row:, model: Sped)
|
create_from_column(column: "Special Ed Status", row:, model: Sped)
|
||||||
create_from_column(column: "Housing", row:, model: Housing)
|
create_from_column(column: "Housing", row:, model: Housing)
|
||||||
|
create_from_column(column: "Language", row:, model: Language)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ class SurveyItemValues
|
||||||
row["Gender"] ||= gender
|
row["Gender"] ||= gender
|
||||||
row["Raw Housing Status"] = raw_housing
|
row["Raw Housing Status"] = raw_housing
|
||||||
row["Housing Status"] = housing
|
row["Housing Status"] = housing
|
||||||
|
row["Home Languages"] = languages.join(",")
|
||||||
|
|
||||||
copy_data_to_main_column(main: /Race/i, secondary: /Race Secondary|Race-1/i)
|
copy_data_to_main_column(main: /Race/i, secondary: /Race Secondary|Race-1/i)
|
||||||
copy_data_to_main_column(main: /Gender/i, secondary: /Gender Secondary|Gender-1/i)
|
copy_data_to_main_column(main: /Gender/i, secondary: /Gender Secondary|Gender-1/i)
|
||||||
|
|
@ -161,7 +162,7 @@ class SurveyItemValues
|
||||||
# Only check the secondary hispanic column if we don't have self reported data and are relying on SIS data
|
# Only check the secondary hispanic column if we don't have self reported data and are relying on SIS data
|
||||||
if self_report.nil? && sis.present?
|
if self_report.nil? && sis.present?
|
||||||
hispanic = value_from(pattern: /Hispanic\s*Latino/i)&.downcase
|
hispanic = value_from(pattern: /Hispanic\s*Latino/i)&.downcase
|
||||||
race_codes = race_codes.reject { |code| code == 5 } if hispanic == "true" && race_codes.count == 1
|
race_codes = race_codes.reject { |code| code == 5 } if ["true", "1"].include?(hispanic) || race_codes.count == 1
|
||||||
race_codes = race_codes.push(4) if %w[true 1].include?(hispanic)
|
race_codes = race_codes.push(4) if %w[true 1].include?(hispanic)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -170,7 +171,7 @@ class SurveyItemValues
|
||||||
end
|
end
|
||||||
|
|
||||||
def lasid
|
def lasid
|
||||||
@lasid ||= value_from(pattern: /LASID/i)
|
@lasid ||= value_from(pattern: /LASID/i) || ""
|
||||||
end
|
end
|
||||||
|
|
||||||
def raw_income
|
def raw_income
|
||||||
|
|
@ -205,6 +206,20 @@ class SurveyItemValues
|
||||||
@housing ||= Housing.to_designation(raw_housing)
|
@housing ||= Housing.to_designation(raw_housing)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def raw_language
|
||||||
|
@raw_language ||= value_from(pattern: /^Language$/i) || ""
|
||||||
|
end
|
||||||
|
|
||||||
|
def languages
|
||||||
|
@languages ||= [].tap do |languages|
|
||||||
|
if raw_language.present?
|
||||||
|
raw_language.split(",").each do |item|
|
||||||
|
languages << Language.to_designation(item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def number_of_children
|
def number_of_children
|
||||||
@number_of_children ||= value_from(pattern: /Number\s*Of\s*Children/i).to_i
|
@number_of_children ||= value_from(pattern: /Number\s*Of\s*Children/i).to_i
|
||||||
end
|
end
|
||||||
|
|
@ -219,6 +234,9 @@ class SurveyItemValues
|
||||||
output ||= row[match]&.strip
|
output ||= row[match]&.strip
|
||||||
end
|
end
|
||||||
|
|
||||||
|
output = output.delete("\u0000") if output.present?
|
||||||
|
output = output.delete("\x00") if output.present?
|
||||||
|
output.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') if output.present?
|
||||||
output
|
output
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,19 +86,31 @@ class SurveyResponsesDataLoader
|
||||||
process_survey_items(row:)
|
process_survey_items(row:)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def languages
|
||||||
|
@languages ||= Language.by_designation
|
||||||
|
end
|
||||||
|
|
||||||
|
def housings
|
||||||
|
@housings ||= Housing.by_designation
|
||||||
|
end
|
||||||
|
|
||||||
def process_survey_items(row:)
|
def process_survey_items(row:)
|
||||||
student = nil
|
student = nil
|
||||||
parent = nil
|
parent = nil
|
||||||
if row.respondent_type == :student
|
if row.respondent_type == :student
|
||||||
student = Student.find_or_create_by(response_id: row.response_id, lasid: row.lasid)
|
student = Student.find_or_create_by(response_id: row.response_id, lasid: row.lasid)
|
||||||
student.races.delete_all
|
student.races.delete_all
|
||||||
tmp_races = row.races.map { |race| races[race] }
|
tmp_races = row.races.map { |race| races[race] }.reject(&:nil?)
|
||||||
student.races += tmp_races
|
student.races += tmp_races
|
||||||
end
|
end
|
||||||
|
|
||||||
if row.respondent_type == :parent
|
if row.respondent_type == :parent
|
||||||
parent = Parent.find_or_create_by(response_id: row.response_id)
|
parent = Parent.find_or_create_by(response_id: row.response_id)
|
||||||
parent.number_of_children = row.number_of_children
|
parent.number_of_children = row.number_of_children
|
||||||
|
tmp_languages = row.languages.map { |language| languages[language] }.reject(&:nil?)
|
||||||
|
parent.languages.delete_all
|
||||||
|
parent.languages.concat(tmp_languages)
|
||||||
|
parent.housing = housings[row.housing] if row.housing.present?
|
||||||
parent.save
|
parent.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,8 @@
|
||||||
<h3 class="sub-header-4 mt-5">Data Filters</h3>
|
<h3 class="sub-header-4 mt-5">Data Filters</h3>
|
||||||
<div class="bg-gray p-3">
|
<div class="bg-gray p-3">
|
||||||
|
|
||||||
<% @presenter.sources.each do |source| %>
|
<% @presenter.sources.each do |source| %>
|
||||||
|
<%# Source options; e.g. 'All Data' or 'Survey Data only' %>
|
||||||
<%= form_with(url: district_school_analyze_index_path,
|
|
||||||
method: :get,
|
|
||||||
data: {
|
|
||||||
turbo_frame: "results",
|
|
||||||
turbo_action: "advance",
|
|
||||||
controller: "analyze",
|
|
||||||
action: "input->analyze#submit"
|
|
||||||
}) do |f| %>
|
|
||||||
|
|
||||||
<% params.reject{|key,_| key == "graph"}.each do |key, value| %>
|
|
||||||
<input type="hidden" id="year" name="<%= key %>" value="<%= value %>">
|
|
||||||
<% end %>
|
|
||||||
<input type="radio"
|
|
||||||
id="<%= source.slug %>"
|
|
||||||
class="form-check-input"
|
|
||||||
name="graph"
|
|
||||||
value="<%= source.graph.slug %>"
|
|
||||||
<%= source.slug == @presenter.source.slug ? "checked" : "" %>>
|
|
||||||
<label for="<%= source.slug %>"><%= source.to_s %></label>
|
|
||||||
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
|
|
||||||
<% if source.slug != "all-data" %>
|
|
||||||
<%= form_with(url: district_school_analyze_index_path,
|
<%= form_with(url: district_school_analyze_index_path,
|
||||||
method: :get,
|
method: :get,
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -36,28 +12,52 @@
|
||||||
action: "input->analyze#submit"
|
action: "input->analyze#submit"
|
||||||
}) do |f| %>
|
}) do |f| %>
|
||||||
|
|
||||||
<% params.reject{|key,_| key == "graph"}.each do |key, value| %>
|
<% params.reject{|key,_| key == "graph"}.each do |key, value| %>
|
||||||
<input type="hidden" id="year" name="<%= key %>" value="<%= value %>">
|
<input type="hidden" id="year" name="<%= key %>" value="<%= value %>">
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% @presenter.slices.each do | slice | %>
|
|
||||||
<div class="d-flex flex-row mx-3">
|
|
||||||
<input type="radio"
|
<input type="radio"
|
||||||
id="<%= slice.slug %>"
|
id="<%= source.slug %>"
|
||||||
class="form-check-input me-2"
|
class="form-check-input"
|
||||||
name="graph"
|
name="graph"
|
||||||
value="<%= slice.graph.slug %>"
|
value="<%= source.graph.slug %>"
|
||||||
<%= slice.slug == @presenter.slice.slug ? "checked" : "" %>
|
<%= source.slug == @presenter.source.slug ? "checked" : "" %>>
|
||||||
<%= slice.slug == "all-data" ? "hidden" : "" %>>
|
<label for="<%= source.slug %>"><%= source.to_s %></label>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<label class="text-break" for="<%= slice.slug %>"
|
|
||||||
<%= slice.slug == "all-data" ? "hidden" : "" %>>
|
<% if source.slug != "all-data" %>
|
||||||
<%= slice.to_s %></label>
|
<%= form_with(url: district_school_analyze_index_path,
|
||||||
</div>
|
method: :get,
|
||||||
|
data: {
|
||||||
|
turbo_frame: "results",
|
||||||
|
turbo_action: "advance",
|
||||||
|
controller: "analyze",
|
||||||
|
action: "input->analyze#submit"
|
||||||
|
}) do |f| %>
|
||||||
|
|
||||||
|
<% params.reject{|key,_| key == "graph"}.each do |key, value| %>
|
||||||
|
<input type="hidden" id="year" name="<%= key %>" value="<%= value %>">
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% @presenter.slices.each do | slice | %>
|
||||||
|
<div class="d-flex flex-row mx-3">
|
||||||
|
<input type="radio"
|
||||||
|
id="<%= slice.slug %>"
|
||||||
|
class="form-check-input me-2"
|
||||||
|
name="graph"
|
||||||
|
value="<%= slice.graph.slug %>"
|
||||||
|
<%= slice.slug == @presenter.slice.slug ? "checked" : "" %>
|
||||||
|
<%= slice.slug == "all-data" ? "hidden" : "" %>>
|
||||||
|
|
||||||
|
<label class="text-break" for="<%= slice.slug %>"
|
||||||
|
<%= slice.slug == "all-data" ? "hidden" : "" %>>
|
||||||
|
<%= slice.to_s %></label>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= render partial: "group_selectors" %>
|
<%= render partial: "group_selectors" %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
Race Qualtrics Code,Race/Ethnicity,Gender Qualtrics Code,Sex/Gender,Income,ELL,Special Ed Status,Housing
|
Race Qualtrics Code,Race/Ethnicity,Gender Qualtrics Code,Sex/Gender,Income,ELL,Special Ed Status,Housing,Language
|
||||||
1,American Indian or Alaskan Native,2,Male,Economically Disadvantaged - N,ELL,Special Education,Own
|
1,American Indian or Alaskan Native,2,Male,Economically Disadvantaged - N,ELL,Special Education,Own,English
|
||||||
2,Asian or Pacific Islander,1,Female,Economically Disadvantaged - Y,Not ELL,Not Special Education,Rent
|
2,Asian or Pacific Islander,1,Female,Economically Disadvantaged - Y,Not ELL,Not Special Education,Rent,Portuguese
|
||||||
3,Black or African American,4,Non-Binary,Unknown,Unknown,Unknown,Unknown
|
3,Black or African American,4,Non-Binary,Unknown,Unknown,Unknown,Unknown,Spanish
|
||||||
4,Hispanic or Latinx,99,Unknown,,,,
|
4,Hispanic or Latinx,99,Unknown,,,,,Prefer not to disclose
|
||||||
5,White or Caucasian,,,,,,
|
5,White or Caucasian,,,,,,,Prefer to self-describe
|
||||||
6,Prefer not to disclose,,,,,,
|
6,Prefer not to disclose,,,,,,,
|
||||||
7,Prefer to self-describe,,,,,,
|
7,Prefer to self-describe,,,,,,,
|
||||||
8,Middle Eastern,,,,,,
|
8,Middle Eastern,,,,,,,
|
||||||
99,Race/Ethnicity Not Listed,,,,,,
|
99,Race/Ethnicity Not Listed,,,,,,,
|
||||||
100,Multiracial,,,,,,
|
100,Multiracial,,,,,,,
|
||||||
|
|
|
||||||
|
5
db/migrate/20250408212201_add_housing_to_parent.rb
Normal file
5
db/migrate/20250408212201_add_housing_to_parent.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddHousingToParent < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_reference :parents, :housing, foreign_key: true
|
||||||
|
end
|
||||||
|
end
|
||||||
10
db/migrate/20250411213850_create_languages.rb
Normal file
10
db/migrate/20250411213850_create_languages.rb
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
class CreateLanguages < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
create_table :languages do |t|
|
||||||
|
t.string :designation
|
||||||
|
t.string :slug
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
12
db/migrate/20250418184427_create_parent_languages.rb
Normal file
12
db/migrate/20250418184427_create_parent_languages.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
class CreateParentLanguages < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
create_table :parent_languages do |t|
|
||||||
|
t.references :parent, null: false, foreign_key: true
|
||||||
|
t.references :language, null: false, foreign_key: true
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :parent_languages, %i[parent_id language_id]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddDesignationIndexToLanguage < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_index :languages, %i[designation]
|
||||||
|
end
|
||||||
|
end
|
||||||
25
db/schema.rb
25
db/schema.rb
|
|
@ -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_03_27_205800) do
|
ActiveRecord::Schema[8.0].define(version: 2025_04_18_185655) 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"
|
||||||
|
|
||||||
|
|
@ -102,6 +102,14 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_27_205800) do
|
||||||
t.index ["slug"], name: "index_incomes_on_slug", unique: true
|
t.index ["slug"], name: "index_incomes_on_slug", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "languages", force: :cascade do |t|
|
||||||
|
t.string "designation"
|
||||||
|
t.string "slug"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["designation"], name: "index_languages_on_designation"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "legacy_attempts", id: :serial, force: :cascade do |t|
|
create_table "legacy_attempts", id: :serial, force: :cascade do |t|
|
||||||
t.integer "recipient_id"
|
t.integer "recipient_id"
|
||||||
t.integer "schedule_id"
|
t.integer "schedule_id"
|
||||||
|
|
@ -322,11 +330,23 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_27_205800) 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_languages", force: :cascade do |t|
|
||||||
|
t.bigint "parent_id", null: false
|
||||||
|
t.bigint "language_id", null: false
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["language_id"], name: "index_parent_languages_on_language_id"
|
||||||
|
t.index ["parent_id", "language_id"], name: "index_parent_languages_on_parent_id_and_language_id"
|
||||||
|
t.index ["parent_id"], name: "index_parent_languages_on_parent_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "parents", force: :cascade do |t|
|
create_table "parents", force: :cascade do |t|
|
||||||
t.string "response_id"
|
t.string "response_id"
|
||||||
t.integer "number_of_children"
|
t.integer "number_of_children"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.bigint "housing_id"
|
||||||
|
t.index ["housing_id"], name: "index_parents_on_housing_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "races", force: :cascade do |t|
|
create_table "races", force: :cascade do |t|
|
||||||
|
|
@ -514,6 +534,9 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_27_205800) 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_languages", "languages"
|
||||||
|
add_foreign_key "parent_languages", "parents"
|
||||||
|
add_foreign_key "parents", "housings"
|
||||||
add_foreign_key "respondents", "academic_years"
|
add_foreign_key "respondents", "academic_years"
|
||||||
add_foreign_key "respondents", "schools"
|
add_foreign_key "respondents", "schools"
|
||||||
add_foreign_key "response_rates", "academic_years"
|
add_foreign_key "response_rates", "academic_years"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,13 @@
|
||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
|
factory :parent_language do
|
||||||
|
parent { nil }
|
||||||
|
language { nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :language do
|
||||||
|
designation { "MyString" }
|
||||||
|
end
|
||||||
|
|
||||||
factory :housing do
|
factory :housing do
|
||||||
designation { "MyString" }
|
designation { "MyString" }
|
||||||
end
|
end
|
||||||
|
|
|
||||||
45
spec/fixtures/demographic_glossary.csv
vendored
45
spec/fixtures/demographic_glossary.csv
vendored
|
|
@ -1,21 +1,24 @@
|
||||||
ELL Value,ELL Type,ELL Headers,Sped Value,Sped Type,Sped Headers,Income Value,Income Type,Income Headers
|
ELL Value,ELL Type,ELL Headers,Sped Value,Sped Type,Sped Headers,Income Value,Income Type,Income Headers,Language Value,Language Type
|
||||||
EL student not 1st year,ELL,EL Student First Year,A,Special Education,Special Ed Status,Free Lunch,Economically Disadvantaged – Y,Low Income
|
EL student not 1st year,ELL,EL Student First Year,A,Special Education,Special Ed Status,Free Lunch,Economically Disadvantaged – Y,Low Income,1,English
|
||||||
"EL student, not 1st year",ELL,Raw ELL,active,Special Education,Raw SPED,Reduced Lunch,Economically Disadvantaged – Y,Raw Income
|
"EL student, not 1st year",ELL,Raw ELL,active,Special Education,Raw SPED,Reduced Lunch,Economically Disadvantaged – Y,Raw Income,2,Portuguese
|
||||||
EL student 1st year,ELL,ELL- SIS,1,Special Education,SPED- SIS,LowIncome,Economically Disadvantaged – Y,SES- SIS
|
EL student 1st year,ELL,ELL- SIS,1,Special Education,SPED- SIS,LowIncome,Economically Disadvantaged – Y,SES- SIS,3,Spanish
|
||||||
"EL student, 1st year",ELL,DirectCert,Special Education,Special Education,SPED,Low Income,Economically Disadvantaged – Y,EconDisadvantaged
|
"EL student, 1st year",ELL,DirectCert,Special Education,Special Education,SPED,Low Income,Economically Disadvantaged – Y,EconDisadvantaged,99,Prefer not to disclose
|
||||||
EL - Early Child. or PK,ELL,ELL,Referred,Not Special Education,,Reduced price lunch,Economically Disadvantaged – Y,Income SIS
|
EL - Early Child. or PK,ELL,ELL,Referred,Not Special Education,,Reduced price lunch,Economically Disadvantaged – Y,Income SIS,100,Prefer to self-describe
|
||||||
1,ELL,English Learner,Ineligible,Not Special Education,,TRUE,Economically Disadvantaged – Y,SES
|
1,ELL,English Learner,Ineligible,Not Special Education,,TRUE,Economically Disadvantaged – Y,SES ,,
|
||||||
lep student 1st year,ELL,,I,Not Special Education,,1,Economically Disadvantaged – Y,DirectCert
|
lep student 1st year,ELL,ELL Status- SIS,I,Not Special Education,,1,Economically Disadvantaged – Y,DirectCert,,
|
||||||
lep student not 1st year,ELL,,exited,Not Special Education,,Not Eligible,Economically Disadvantaged – N,
|
lep student not 1st year,ELL,,exited,Not Special Education,,Not Eligible,Economically Disadvantaged – N,,,
|
||||||
LEP Not1stYr,ELL,,0,Not Special Education,,FALSE,Economically Disadvantaged – N,
|
LEP Not1stYr,ELL,,0,Not Special Education,,FALSE,Economically Disadvantaged – N,,,
|
||||||
LEP1stYr US Sch,ELL,,Not Special Education,Not Special Education,,0,Economically Disadvantaged – N,
|
LEP1stYr US Sch,ELL,,Not Special Education,Not Special Education,,0,Economically Disadvantaged – N,,,
|
||||||
Does not apply,Not ELL,,Does not apply,Not Special Education,,[blanks],Economically Disadvantaged – N,
|
Does not apply,Not ELL,,Does not apply,Not Special Education,,[blanks],Economically Disadvantaged – N,,,
|
||||||
0,Not ELL,,[blanks],Not Special Education,,#NA,Unknown,
|
0,Not ELL,,[blanks],Unknown,,#NA,Unknown,,,
|
||||||
2,Not ELL,,#NA,Unknown,,NA,Unknown,
|
2,Not ELL,,#NA,Unknown,,NA,Unknown,,,
|
||||||
3,Not ELL,,NA,Unknown,,N/A,Unknown,
|
3,Not ELL,,NA,Unknown,,N/A,Unknown,,,
|
||||||
[blanks],Not ELL,,N/A,Unknown,,#N/A,Unknown,
|
[blanks],Not ELL,,N/A,Unknown,,#N/A,Unknown,,,
|
||||||
#NA,Unknown,,#N/A,Unknown,,Income,Unknown,
|
#NA,Unknown,,#N/A,Unknown,,Income,Unknown,,,
|
||||||
NA,Unknown,,SPED,Unknown,,Yes,Economically Disadvantaged – Y,
|
NA,Unknown,,SPED,Unknown,,Yes,Economically Disadvantaged – Y,,,
|
||||||
N/A,Unknown,,No special needs,Not Special Education,,No,Economically Disadvantaged – N,
|
N/A,Unknown,,No special needs,Not Special Education,,No,Economically Disadvantaged – N,,,
|
||||||
#N/A,Unknown,,,,,,,
|
#N/A,Unknown,,Not SPED,Not Special Education,,,,,,
|
||||||
ELL,ELL,,,,,,,
|
ELL,ELL,,,,,,,,,
|
||||||
|
LEP Not 1st Year,ELL,,,,,,,,,
|
||||||
|
Yes,ELL,,,,,,,,,
|
||||||
|
No,Not ELL,,,,,,,,,
|
||||||
|
|
|
||||||
|
5
spec/models/language_spec.rb
Normal file
5
spec/models/language_spec.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Language, type: :model do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
||||||
5
spec/models/parent_language_spec.rb
Normal file
5
spec/models/parent_language_spec.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe ParentLanguage, type: :model do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
||||||
|
|
@ -366,38 +366,37 @@ describe Analyze::Presenter do
|
||||||
|
|
||||||
context ".group" do
|
context ".group" do
|
||||||
context "when no parameters are provided" do
|
context "when no parameters are provided" do
|
||||||
it "returns the first item in the list of groups" do
|
it "returns no groups when no params are defined" do
|
||||||
params = {}
|
presenter = Analyze::Presenter.new(params: {}, school:, academic_year:)
|
||||||
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
expect(presenter.groups).to eq []
|
||||||
expect(presenter.group.slug).to eq presenter.groups.first.slug
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when a group is provided in the params hash" do
|
context "when a group is provided in the params hash" do
|
||||||
it "returns the group with the given slug" do
|
it "returns the group with the given slug" do
|
||||||
params = { group: "gender" }
|
params = { group: "gender", graph: "students-by-gender" }
|
||||||
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
||||||
expect(presenter.group.slug).to eq "gender"
|
expect(presenter.group.slug).to eq "gender"
|
||||||
|
|
||||||
params = { group: "grade" }
|
params = { group: "grade", graph: "students-by-grade" }
|
||||||
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
||||||
expect(presenter.group.slug).to eq "grade"
|
expect(presenter.group.slug).to eq "grade"
|
||||||
|
|
||||||
params = { group: "race" }
|
params = { group: "race", graph: "students-by-race" }
|
||||||
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
||||||
expect(presenter.group.slug).to eq "race"
|
expect(presenter.group.slug).to eq "race"
|
||||||
|
|
||||||
params = { group: "income" }
|
params = { group: "income", graph: "students-by-income" }
|
||||||
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
||||||
expect(presenter.group.slug).to eq "income"
|
expect(presenter.group.slug).to eq "income"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when a parameter that does not match a group is provided" do
|
context "when a parameter that does not match a group is provided" do
|
||||||
it "returns the first item in the list of groups" do
|
it "returns nil when invalid parameters are given" do
|
||||||
params = { group: "invalid group" }
|
params = { group: "invalid group", graph: "invalid graph" }
|
||||||
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
presenter = Analyze::Presenter.new(params:, school:, academic_year:)
|
||||||
expect(presenter.group.slug).to eq presenter.groups.first.slug
|
expect(presenter.group).to eq nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -301,6 +301,7 @@ end
|
||||||
|
|
||||||
def reads_headers_from_raw_csv(processed_data)
|
def reads_headers_from_raw_csv(processed_data)
|
||||||
processed_data in [headers, clean_csv, log_csv, data]
|
processed_data in [headers, clean_csv, log_csv, data]
|
||||||
|
|
||||||
expect(headers.to_set.sort).to eq ["StartDate", "EndDate", "Status", "IPAddress", "Progress", "Duration (in seconds)",
|
expect(headers.to_set.sort).to eq ["StartDate", "EndDate", "Status", "IPAddress", "Progress", "Duration (in seconds)",
|
||||||
"Finished", "RecordedDate", "ResponseId", "District", "School",
|
"Finished", "RecordedDate", "ResponseId", "District", "School",
|
||||||
"LASID", "Gender", "Race", "What grade are you in?", "s-tint-q1",
|
"LASID", "Gender", "Race", "What grade are you in?", "s-tint-q1",
|
||||||
|
|
@ -314,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"].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"].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)
|
||||||
|
|
|
||||||
|
|
@ -414,7 +414,7 @@ RSpec.describe SurveyItemValues, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when there are multiple races" do
|
context "when there are multiple races" do
|
||||||
it "returns the gender that maps to the gender provided" do
|
it "returns the race that maps to the race provided" do
|
||||||
row = { "Race" => "1,2,3" }
|
row = { "Race" => "1,2,3" }
|
||||||
values = SurveyItemValues.new(row:, headers:, survey_items:, schools:, academic_years:)
|
values = SurveyItemValues.new(row:, headers:, survey_items:, schools:, academic_years:)
|
||||||
expect(values.races).to eq [1, 2, 3, 100]
|
expect(values.races).to eq [1, 2, 3, 100]
|
||||||
|
|
@ -452,7 +452,7 @@ RSpec.describe SurveyItemValues, type: :model do
|
||||||
headers.push("HispanicLatino")
|
headers.push("HispanicLatino")
|
||||||
headers.push("Race- SIS")
|
headers.push("Race- SIS")
|
||||||
values = SurveyItemValues.new(row:, headers:, survey_items:, schools:, academic_years:)
|
values = SurveyItemValues.new(row:, headers:, survey_items:, schools:, academic_years:)
|
||||||
expect(values.races).to eq [5, 2, 3, 4, 100]
|
expect(values.races).to eq [2, 3, 4, 100]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -567,6 +567,22 @@ RSpec.describe SurveyItemValues, type: :model do
|
||||||
# end
|
# end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context ".language" do
|
||||||
|
before :each do
|
||||||
|
attleboro
|
||||||
|
ay_2022_23
|
||||||
|
end
|
||||||
|
|
||||||
|
it "validates the code matches the expectations defined in the demographic_glossary" do
|
||||||
|
|
||||||
|
list = read(demographic_filepath, "Language Value", "Language Type")
|
||||||
|
|
||||||
|
list.each do |target, result|
|
||||||
|
compare("Language", target, [result], :languages)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context ".ell" do
|
context ".ell" do
|
||||||
before :each do
|
before :each do
|
||||||
attleboro
|
attleboro
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,12 @@ describe SurveyResponsesDataLoader do
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let(:housings) do
|
||||||
|
create(:housing, designation: "Own")
|
||||||
|
create(:housing, designation: "Rent")
|
||||||
|
create(:housing, designation: "Unknown")
|
||||||
|
end
|
||||||
|
|
||||||
let(:t_pcom_q3) { create(:survey_item, survey_item_id: "t-pcom-q3") }
|
let(:t_pcom_q3) { create(:survey_item, survey_item_id: "t-pcom-q3") }
|
||||||
let(:t_pcom_q2) { create(:survey_item, survey_item_id: "t-pcom-q2") }
|
let(:t_pcom_q2) { create(:survey_item, survey_item_id: "t-pcom-q2") }
|
||||||
let(:t_coll_q1) { create(:survey_item, survey_item_id: "t-coll-q1") }
|
let(:t_coll_q1) { create(:survey_item, survey_item_id: "t-coll-q1") }
|
||||||
|
|
@ -123,12 +129,20 @@ describe SurveyResponsesDataLoader do
|
||||||
let(:unknown_race) { create(:race, qualtrics_code: 99) }
|
let(:unknown_race) { create(:race, qualtrics_code: 99) }
|
||||||
let(:multiracial) { create(:race, qualtrics_code: 100) }
|
let(:multiracial) { create(:race, qualtrics_code: 100) }
|
||||||
|
|
||||||
|
let(:languages){
|
||||||
|
create(:language, designation: "English")
|
||||||
|
create(:language, designation: "Spanish")
|
||||||
|
create(:language, designation: "Portuguese")
|
||||||
|
create(:language, designation: "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
let(:setup) do
|
let(:setup) do
|
||||||
ay_2020_21
|
ay_2020_21
|
||||||
ay_2022_23
|
ay_2022_23
|
||||||
school
|
school
|
||||||
second_school
|
second_school
|
||||||
butler_school
|
butler_school
|
||||||
|
housings
|
||||||
t_pcom_q3
|
t_pcom_q3
|
||||||
t_pcom_q2
|
t_pcom_q2
|
||||||
t_coll_q1
|
t_coll_q1
|
||||||
|
|
@ -161,6 +175,8 @@ describe SurveyResponsesDataLoader do
|
||||||
middle_eastern
|
middle_eastern
|
||||||
unknown_race
|
unknown_race
|
||||||
multiracial
|
multiracial
|
||||||
|
|
||||||
|
languages
|
||||||
end
|
end
|
||||||
|
|
||||||
before :each do
|
before :each do
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue