parent
8c7767d0b9
commit
12e4e3f177
@ -1,4 +1,6 @@
|
||||
class Race < ApplicationRecord
|
||||
include FriendlyId
|
||||
has_many :student_races
|
||||
has_many :students, through: :student_races
|
||||
friendly_id :designation, use: [:slugged]
|
||||
end
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
class Student < ApplicationRecord
|
||||
has_many :survey_item_responses
|
||||
has_many :student_races
|
||||
has_many :races, through: :student_races
|
||||
|
||||
encrypts :lasid, deterministic: true
|
||||
end
|
||||
@ -0,0 +1,4 @@
|
||||
class StudentRace < ApplicationRecord
|
||||
belongs_to :student
|
||||
belongs_to :race
|
||||
end
|
||||
@ -0,0 +1,74 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# SurveyItemResponse.where(student: StudentRace.where(race: Race.find_by_qualtrics_code(8)).limit(10).map(&:student)).count
|
||||
require 'csv'
|
||||
|
||||
class StudentLoader
|
||||
def self.load_data(filepath:)
|
||||
File.open(filepath) do |file|
|
||||
headers = file.first
|
||||
|
||||
students = []
|
||||
file.lazy.each_slice(1000) do |lines|
|
||||
CSV.parse(lines.join, headers:).map do |row|
|
||||
# students << process_row(row:)
|
||||
process_row(row:)
|
||||
end
|
||||
end
|
||||
# Student.import students.compact.flatten.to_set.to_a, batch_size: 1000,
|
||||
# on_duplicate_key_update: { conflict_target: [:id] }
|
||||
end
|
||||
end
|
||||
|
||||
def self.process_row(row:)
|
||||
race_codes = row['RACE'] || row['What is your race/ethnicity?(Please select all that apply) - Selected Choice'] || '99'
|
||||
race_codes = race_codes.split(',').map(&:to_i) || []
|
||||
races = process_races(codes: race_codes)
|
||||
response_id = row['ResponseId'] || row['Responseid'] || row['ResponseID'] ||
|
||||
row['Response ID'] || row['Response id'] || row['Response Id']
|
||||
lasid = row['LASID'] || row['lasid']
|
||||
return nil if student_exists?(response_id:)
|
||||
|
||||
student = create_student(response_id:, lasid:, races:)
|
||||
|
||||
assign_student_to_responses(response_id:, student:)
|
||||
student
|
||||
end
|
||||
|
||||
def self.student_exists?(response_id:)
|
||||
Student.find_by_response_id(response_id).present?
|
||||
end
|
||||
|
||||
def self.assign_student_to_responses(response_id:, student:)
|
||||
survey_responses = SurveyItemResponse.where(response_id:)
|
||||
survey_responses.each do |response|
|
||||
response.student = student
|
||||
response.save
|
||||
end
|
||||
|
||||
# SurveyItemResponse.import survey_responses, on_duplicate_key_update: { conflict_target: [:id], columns: [:student] }
|
||||
end
|
||||
|
||||
def self.create_student(response_id:, lasid:, races:)
|
||||
student = Student.new(response_id:)
|
||||
races.each do |race|
|
||||
student.races << race
|
||||
end
|
||||
student.lasid = lasid
|
||||
student.save
|
||||
student
|
||||
end
|
||||
|
||||
def self.process_races(codes:)
|
||||
codes = codes.map do |code|
|
||||
code = 99 if [6, 7].include?(code)
|
||||
Race.find_by_qualtrics_code(code)
|
||||
end
|
||||
remove_unknown_race_if_other_races_present(races: codes.to_set)
|
||||
end
|
||||
|
||||
def self.remove_unknown_race_if_other_races_present(races:)
|
||||
races.delete(Race.find_by_qualtrics_code(99)) if races.length > 1
|
||||
races
|
||||
end
|
||||
end
|
||||
@ -1 +1 @@
|
||||
BT6iQXFC9KSTrl2ERWJBrgTjSC+hpRj7v3VexKptLx5m2H20A4nUNx8ng2z/Px/47FBVtTUpyBBPf1yubbLZWs6VNsKzgmhUGiWjZ3x0UzQChPN6tgR1dNN34Olbr8eBvlWacb/VwrJysoHf+OR+MpPWdxqZNgoruqHXgJgU7xs24+MUVUiqUC80v0GDzar7aTEwXZFIOA==--O8YzbfYG1w8ZcEVp--He1+cpuOPDgYOAEXRLyzxA==
|
||||
CCr3H/C8F7QRySYJv3rjuU7vTlntvEc84yqA5Ll76J5bwsJpYnbPymlO66Y2TzwAJe2+4Ft8TCspBr0lnfKM8gKdhUWkbyxwUOdiFi/5yilI/k7fE1W2mlPVUQHyePoq0+VolP4TITIcrXvstLCV42ooXeKYrHnRw+Nql3VzKRRJlmtnt9HxLsta+L5p3emCnUTL96LszUjYMtdB8T4uujyHjmKqzC+5lS2IqfUeW82g8LfeuTVcxqiKUce+ZywBGZjLlOIrFVndqV9vAV6U6hOnqXzEW7Tl184zt5OIfq6qkhKp/L2xTnJxVFZS+eNCiffBqQ==--PsX6hrtFTNQaK+zu--N0QfgNulvjEoGj6Nl6iE7g==
|
||||
@ -1 +1 @@
|
||||
KX2iu27u/BXglSTHH4yD2ApSFEgZxn9C3EyJq151WIMH8ZSI6ThlF4tOhekwXkbTBxH4--2INMwwXnnq/Q1ur4--RBKY0uu9FmKTbxarieTWiQ==
|
||||
pEFclvEWB+uo//cOuEU7FHhFBNOMyDFTtc8NZeKmqPPaHI0MzfTonSrYMSD2awmUI5hbm+OJaGmBBElpVmGExEXH8Jc3282Vxrk3szBIWuq0rulg227hcatVtlRVri1vyhUCDPMOz89jc1FnHx/zMW62zRYgwIrNjZ7BU2WaoELy+xz8EKEEIcXC47Zg4wBM/omGuj2fkcO3R5Fvm39H0dAYhPL/JzFsUpyXGqXJFMNVN1ImJlNX8cfVYj31VMM4EROB6XOR1Hnx/Hq6AqAbFH/v5lh+B6KgMJoYA2AEOsZdj+y6NuCIXhxn0HnAlEqxFf9MSw==--QMoBHlvTP2/cnr4q--rpnKseZ3ToVmMDKE9dhqkA==
|
||||
@ -1 +0,0 @@
|
||||
R+Ip8wqfVzRwuVraYG4cubh3oUHbJjat8ddjCwB30HQLKIOsuxiSH9oUEP2yTmXG3iTx--t7wIdTiRrs7eOVB7--0x4CV22/Jl2ElPzaFT/ICA==
|
||||
@ -1 +1 @@
|
||||
LVLki98j5ziVOtGhQhXvB/iCF3qVFR98ztFGyi+uFYh1Ma2sRu72TJGMc0Wk29BD15F0ytNsgmBpQUwmk4Mrwoq7RIAd8sODbnfD9ScC4eguvCS8gN8NpU3NYnuZEbrw3xFOvH+apfKYlo5jomoGV2hytEW7WQkUNIE+M1TjYU0FFYkKs0F6ovw/xdMBGhzFZndjfU4BAg==--NE3oTAKz9bImGD1M--vlT/dy8GZunUkoovq2g+SA==
|
||||
9WrwvS2cg9KTeIG7QRV22i13cNQZifGdx3x9SK/FfHTIZgxAeoK2tzDv6kr51+CPBeZxK1jPazx4fKh0/UVkRTF+KoxG376Sw1RnV72ahd47xPdaRUzbWWKcsEErIDc9BsLEThhHA4CG6ZcQmF7h42vvfLDbVrResL6dz5PZfWRtN20o1nMPJnJRHP+9umgkWo3QU7qr/7vYfu9C5iSRmaColnO7vaGR+pglCfY+ezbkAI3vZx3uleepvygnFDcrptqCbrGs/gsvxq/sXJbG2MsEiZk+NWWr7ApcGPjtLsRjjXqNZ7p3vbTiYIviDe9JPbdXoc9NXN/fp4REMX4=--2MXdu/2sPS/aO59/--iy1RPBMtri9m/qor0xgK0A==
|
||||
@ -0,0 +1 @@
|
||||
,nelson,tripper,29.07.2022 14:28,file:///home/nelson/.config/libreoffice/4;
|
||||
|
Can't render this file because it is too large.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,11 @@
|
||||
class CreateNewStudent < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :students do |t|
|
||||
t.string :lasid
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :students, :lasid
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,5 @@
|
||||
class AddStudentToSurveyItemResponse < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_reference :survey_item_responses, :student, foreign_key: true
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,5 @@
|
||||
class AddResponseIdToStudent < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :students, :response_id, :string
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,10 @@
|
||||
class CreateStudentRaces < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :student_races do |t|
|
||||
t.references :student, null: false, foreign_key: true
|
||||
t.references :race, null: false, foreign_key: true
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe StudentRace, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
||||
@ -0,0 +1,74 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe StudentLoader do
|
||||
let(:path_to_student_responses) { Rails.root.join('spec', 'fixtures', 'test_2020-21_student_survey_responses.csv') }
|
||||
let(:american_indian) { Race.find_by_qualtrics_code(1) }
|
||||
let(:asian) { Race.find_by_qualtrics_code(2) }
|
||||
let(:black) { Race.find_by_qualtrics_code(3) }
|
||||
let(:latinx) { Race.find_by_qualtrics_code(4) }
|
||||
let(:white) { Race.find_by_qualtrics_code(5) }
|
||||
let(:middle_eastern) { Race.find_by_qualtrics_code(8) }
|
||||
let(:unknown) { Race.find_by_qualtrics_code(99) }
|
||||
|
||||
before :each do
|
||||
Rails.application.load_seed
|
||||
end
|
||||
|
||||
after :each do
|
||||
DatabaseCleaner.clean
|
||||
end
|
||||
describe '#process_races' do
|
||||
context 'as a standalone function' do
|
||||
it 'race codes of 6 or 7 get classified as an unknown race' do
|
||||
codes = [6]
|
||||
expect(StudentLoader.process_races(codes:)).to eq Set[unknown]
|
||||
codes = [7]
|
||||
expect(StudentLoader.process_races(codes:)).to eq Set[unknown]
|
||||
codes = [6, 7]
|
||||
expect(StudentLoader.process_races(codes:)).to eq Set[unknown]
|
||||
codes = [1, 6, 7]
|
||||
expect(StudentLoader.process_races(codes:)).to eq Set[american_indian]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'self.load_data' do
|
||||
context 'student survey responses' do
|
||||
before :each do
|
||||
SurveyResponsesDataLoader.load_data filepath: path_to_student_responses
|
||||
StudentLoader.load_data filepath: path_to_student_responses
|
||||
end
|
||||
|
||||
it 'ensures student responses load correctly' do
|
||||
assigns_student_to_the_survey_item_responses
|
||||
assigns_races_to_students
|
||||
is_idempotent_for_students
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def assigns_student_to_the_survey_item_responses
|
||||
expect(SurveyItemResponse.find_by_response_id('student_survey_response_1').student).not_to eq nil
|
||||
expect(SurveyItemResponse.find_by_response_id('student_survey_response_1').student).to eq Student.find_by_lasid('123456')
|
||||
expect(SurveyItemResponse.find_by_response_id('student_survey_response_6').student).not_to eq nil
|
||||
expect(SurveyItemResponse.find_by_response_id('student_survey_response_6').student).to eq Student.find_by_response_id('student_survey_response_6')
|
||||
end
|
||||
|
||||
def assigns_races_to_students
|
||||
expect(Student.find_by_response_id('student_survey_response_1').races).to eq [american_indian]
|
||||
expect(Student.find_by_response_id('student_survey_response_2').races).to eq [asian, black, latinx]
|
||||
expect(Student.find_by_response_id('student_survey_response_3').races).to eq [unknown]
|
||||
expect(Student.find_by_response_id('student_survey_response_4').races).to eq [unknown]
|
||||
expect(Student.find_by_response_id('student_survey_response_5').races).to eq [american_indian, asian, black, latinx, white,
|
||||
middle_eastern]
|
||||
expect(Student.find_by_response_id('student_survey_response_6').races).to eq [american_indian, asian, black, latinx, white,
|
||||
middle_eastern]
|
||||
expect(Student.find_by_response_id('student_survey_response_7').races).to eq [unknown]
|
||||
end
|
||||
|
||||
def is_idempotent_for_students
|
||||
number_of_students = Student.count
|
||||
StudentLoader.load_data filepath: path_to_student_responses
|
||||
expect(Student.count).to eq number_of_students
|
||||
end
|
||||
Loading…
Reference in new issue