diff --git a/app/models/context.rb b/app/models/context.rb new file mode 100644 index 0000000..f054b60 --- /dev/null +++ b/app/models/context.rb @@ -0,0 +1,10 @@ +# A Context reflects a demographic category. +class Context < ApplicationRecord + + validates_presence_of :name + validates_presence_of :display_name + validates_uniqueness_of :name + + has_many :questions + +end diff --git a/app/models/question.rb b/app/models/question.rb index be30a88..3ac58cf 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -1,33 +1,10 @@ # A Question is a representation of a survey question. # This class provides convenience methods for navigating question keys and labels, as well as selecting topical subsets of questions. # For now, Questions are hardcoded and not persisted. -class Question +class Question < ApplicationRecord - attr_accessor :key, :label - - QUESTIONS = { - age_given: "Age", - age_exp: "Experience with Age", - klass_given: "Class", - klass_exp: "Experience with Class", - race_ethnicity_given: "Race/Ethnicity", - race_ethnicity_exp: "Experience with Race/Ethnicity", - religion_given: "Religion", - religion_exp: "Experience with Religion", - disability_given: "Disability", - disability_exp: "Experience with Disability", - neurodiversity_given: "Neurodiversity", - neurodiversity_exp: "Experience with Neurodiversity", - gender_given: "Gender", - gender_exp: "Experience with Gender", - lgbtqia_given: "LGBTQIA+ Status", - lgbtqia_exp: "Experience with LGBTQIA+", - pronouns_given: "Pronouns Given", - pronouns_exp: "Experience with Pronouns", - pronouns_feel: "Pronoun Feelings", - affinity: "Identity Affinities", - notes: "Identity Reflection" - } + has_many :responses + belongs_to :context def self.from(key) new(key: key, label: QUESTIONS[key.to_sym]) @@ -45,15 +22,6 @@ def self.freeform_questions [:pronouns_feel, :affinity, :notes] end - def initialize(attrs={}) - self.key = attrs[:key] - self.label = attrs[:label] - end - - def context - "#{self.key}".gsub("_given","").gsub("klass","class").gsub("_exp", "").gsub("_","-") - end - def codes_field "#{self.key}_codes".gsub("given","id") end diff --git a/app/models/response.rb b/app/models/response.rb new file mode 100644 index 0000000..95551ad --- /dev/null +++ b/app/models/response.rb @@ -0,0 +1,6 @@ +class Response < ApplicationRecord + + belongs_to :survey_response + belongs_to :question + +end diff --git a/app/models/survey_response.rb b/app/models/survey_response.rb index 8ffdabc..3f1b26c 100644 --- a/app/models/survey_response.rb +++ b/app/models/survey_response.rb @@ -13,6 +13,7 @@ class SurveyResponse < ApplicationRecord validates_uniqueness_of :response_id has_one :annotation + has_many :responses # Displays the query and its explanation for locating the SurveyResponse's associated Persona in the graph. def graph_query diff --git a/db/migrate/20241029003225_create_contexts.rb b/db/migrate/20241029003225_create_contexts.rb new file mode 100644 index 0000000..fc0f5cb --- /dev/null +++ b/db/migrate/20241029003225_create_contexts.rb @@ -0,0 +1,9 @@ +class CreateContexts < ActiveRecord::Migration[7.2] + def change + create_table :contexts do |t| + t.string :name + t.string :display_name + t.timestamps + end + end +end diff --git a/db/migrate/20241029003455_populate_default_contexts.rb b/db/migrate/20241029003455_populate_default_contexts.rb new file mode 100644 index 0000000..27aefd6 --- /dev/null +++ b/db/migrate/20241029003455_populate_default_contexts.rb @@ -0,0 +1,16 @@ +class PopulateDefaultContexts < ActiveRecord::Migration[7.2] + def change + Context.create(name: "age", display_name: "Age") + Context.create(name: "class", display_name: "Class") + Context.create(name: "race-ethnicity", display_name: "Race/Ethnicity") + Context.create(name: "religion", display_name: "Religion") + Context.create(name: "disability", display_name: "Disability") + Context.create(name: "neurodiversity", display_name: "Neurodiversity") + Context.create(name: "gender", display_name: "Gender") + Context.create(name: "lgbtqia", display_name: "LGBTQIA+ Status") + Context.create(name: "pronouns", display_name: "Pronouns") + Context.create(name: "pronoun_feelings", display_name: "Pronoun Feelings") + Context.create(name: "identity_affinities", display_name: "Identity Affinities") + Context.create(name: "identity_reflection", display_name: "Identity Reflection") + end +end diff --git a/db/migrate/20241029004905_create_questions.rb b/db/migrate/20241029004905_create_questions.rb new file mode 100644 index 0000000..e99f21d --- /dev/null +++ b/db/migrate/20241029004905_create_questions.rb @@ -0,0 +1,15 @@ +class CreateQuestions < ActiveRecord::Migration[7.2] + def change + create_table :questions do |t| + t.string :key + t.string :label + t.boolean :is_experience, default: false + t.boolean :is_identity, default: false + t.boolean :is_feeling, default: false + t.boolean :is_affinity, default: false + t.boolean :is_reflection, default: false + t.timestamps + end + add_reference :questions, :context, null: true, foreign_key: true + end +end diff --git a/db/migrate/20241029010233_populate_default_questions.rb b/db/migrate/20241029010233_populate_default_questions.rb new file mode 100644 index 0000000..2b9bb83 --- /dev/null +++ b/db/migrate/20241029010233_populate_default_questions.rb @@ -0,0 +1,25 @@ +class PopulateDefaultQuestions < ActiveRecord::Migration[7.2] + def change + Question.create(key: 'age_given', label: "Age", is_identity: true, context_id: Context.find_by(name: 'age').id) + Question.create(key: 'age_exp', label: "Experience with Age", is_experience: true, context_id: Context.find_by(name: 'age').id) + Question.create(key: 'klass_given', label: "Class", is_identity: true, context_id: Context.find_by(name: 'class').id) + Question.create(key: 'klass_exp', label: "Experience with Class", is_experience: true, context_id: Context.find_by(name: 'class').id) + Question.create(key: 'race_ethnicity_given', label: "Race/Ethnicity", is_identity: true, context_id: Context.find_by(name: 'race-ethnicity').id) + Question.create(key: 'race_ethnicity_exp', label: "Experience with Race/Ethnicity", is_experience: true, context_id: Context.find_by(name: 'race-ethnicity').id) + Question.create(key: 'religion_given', label: "Religion", is_identity: true, context_id: Context.find_by(name: 'religion').id) + Question.create(key: 'religion_exp', label: "Experience with Religion", is_experience: true, context_id: Context.find_by(name: 'religion').id) + Question.create(key: 'disability_given', label: "Disability", is_identity: true, context_id: Context.find_by(name: 'disability').id) + Question.create(key: 'disability_exp', label: "Experience with Disability", is_experience: true, context_id: Context.find_by(name: 'disability').id) + Question.create(key: 'neurodiversity_given', label: "Neurodiversity", is_identity: true, context_id: Context.find_by(name: 'neurodiversity').id) + Question.create(key: 'neurodiversity_exp', label: "Experience with Neurodiversity", is_experience: true, context_id: Context.find_by(name: 'neurodiversity').id) + Question.create(key: 'gender_given', label: "Gender", is_identity: true, context_id: Context.find_by(name: 'gender').id) + Question.create(key: 'gender_exp', label: "Experience with Gender", is_experience: true, context_id: Context.find_by(name: 'gender').id) + Question.create(key: 'lgbtqia_given', label: "LGBTQIA+ Status", is_identity: true, context_id: Context.find_by(name: 'lgbtqia').id) + Question.create(key: 'lgbtqia_exp', label: "Experience with LGBTQIA+", is_experience: true, context_id: Context.find_by(name: 'lgbtqia').id) + Question.create(key: 'pronouns_given', label: "Pronouns Given", is_identity: true, context_id: Context.find_by(name: 'pronouns').id) + Question.create(key: 'pronouns_exp', label: "Experience with Pronouns", is_experience: true, context_id: Context.find_by(name: 'pronouns').id) + Question.create(key: 'pronouns_feel', label: "Pronoun Feelings", is_feeling: true, context_id: Context.find_by(name: 'pronoun_feelings').id) + Question.create(key: 'affinity', label: "Identity Affinities", is_affinity: true, context_id: Context.find_by(name: 'identity_affinities').id) + Question.create(key: 'notes', label: "Identity Reflection", is_reflection: true, context_id: Context.find_by(name: 'identity_reflection').id) + end +end diff --git a/db/migrate/20241029011624_create_responses.rb b/db/migrate/20241029011624_create_responses.rb new file mode 100644 index 0000000..2801fad --- /dev/null +++ b/db/migrate/20241029011624_create_responses.rb @@ -0,0 +1,11 @@ +class CreateResponses < ActiveRecord::Migration[7.2] + def change + create_table :responses do |t| + t.text :value + t.string :raw_codes, array: true, default: [] + t.timestamps + end + add_reference :responses, :question, null: false, foreign_key: true + add_reference :responses, :survey_response, null: false, foreign_key: true + end +end diff --git a/db/migrate/20241029012413_populate_responses.rb b/db/migrate/20241029012413_populate_responses.rb new file mode 100644 index 0000000..961373b --- /dev/null +++ b/db/migrate/20241029012413_populate_responses.rb @@ -0,0 +1,32 @@ +class PopulateResponses < ActiveRecord::Migration[7.2] + def up + SurveyResponse.all.each do |survey_response| + Response.create(question_id: Question.find_by(key: 'age_given').id, survey_response_id: survey_response.id, value: survey_response.age_given, raw_codes: survey_response.age_id_codes) + Response.create(question_id: Question.find_by(key: 'age_exp').id, survey_response_id: survey_response.id, value: survey_response.age_exp, raw_codes: survey_response.age_exp_codes) + Response.create(question_id: Question.find_by(key: 'klass_given').id, survey_response_id: survey_response.id, value: survey_response.klass_given, raw_codes: survey_response.klass_id_codes) + Response.create(question_id: Question.find_by(key: 'klass_exp').id, survey_response_id: survey_response.id, value: survey_response.klass_exp, raw_codes: survey_response.klass_exp_codes) + Response.create(question_id: Question.find_by(key: 'race_ethnicity_given').id, survey_response_id: survey_response.id, value: survey_response.race_ethnicity_given, raw_codes: survey_response.race_ethnicity_id_codes) + Response.create(question_id: Question.find_by(key: 'race_ethnicity_exp').id, survey_response_id: survey_response.id, value: survey_response.race_ethnicity_exp, raw_codes: survey_response.race_ethnicity_exp_codes) + Response.create(question_id: Question.find_by(key: 'religion_given').id, survey_response_id: survey_response.id, value: survey_response.religion_given, raw_codes: survey_response.religion_id_codes) + Response.create(question_id: Question.find_by(key: 'religion_exp').id, survey_response_id: survey_response.id, value: survey_response.religion_exp, raw_codes: survey_response.religion_exp_codes) + Response.create(question_id: Question.find_by(key: 'disability_given').id, survey_response_id: survey_response.id, value: survey_response.disability_given, raw_codes: survey_response.disability_id_codes) + Response.create(question_id: Question.find_by(key: 'disability_exp').id, survey_response_id: survey_response.id, value: survey_response.disability_exp, raw_codes: survey_response.disability_exp_codes) + Response.create(question_id: Question.find_by(key: 'neurodiversity_given').id, survey_response_id: survey_response.id, value: survey_response.neurodiversity_given, raw_codes: survey_response.neurodiversity_id_codes) + Response.create(question_id: Question.find_by(key: 'neurodiversity_exp').id, survey_response_id: survey_response.id, value: survey_response.neurodiversity_exp, raw_codes: survey_response.neurodiversity_exp_codes) + Response.create(question_id: Question.find_by(key: 'gender_given').id, survey_response_id: survey_response.id, value: survey_response.gender_given, raw_codes: survey_response.gender_id_codes) + Response.create(question_id: Question.find_by(key: 'gender_exp').id, survey_response_id: survey_response.id, value: survey_response.gender_exp, raw_codes: survey_response.gender_exp_codes) + Response.create(question_id: Question.find_by(key: 'lgbtqia_given').id, survey_response_id: survey_response.id, value: survey_response.lgbtqia_given, raw_codes: survey_response.lgbtqia_id_codes) + Response.create(question_id: Question.find_by(key: 'lgbtqia_exp').id, survey_response_id: survey_response.id, value: survey_response.lgbtqia_exp, raw_codes: survey_response.lgbtqia_exp_codes) + Response.create(question_id: Question.find_by(key: 'pronouns_given').id, survey_response_id: survey_response.id, value: survey_response.pronouns_given, raw_codes: survey_response.pronouns_id_codes) + Response.create(question_id: Question.find_by(key: 'pronouns_exp').id, survey_response_id: survey_response.id, value: survey_response.pronouns_exp, raw_codes: survey_response.pronouns_exp_codes) + Response.create(question_id: Question.find_by(key: 'pronouns_feel').id, survey_response_id: survey_response.id, value: survey_response.pronouns_feel, raw_codes: survey_response.pronouns_feel_codes) + Response.create(question_id: Question.find_by(key: 'affinity').id, survey_response_id: survey_response.id, value: survey_response.affinity, raw_codes: survey_response.affinity_codes) + end + end + + def down + Response.destroy_all + end + +end + diff --git a/db/schema.rb b/db/schema.rb index a36639f..5e99ed5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,8 +10,9 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_10_10_001302) do +ActiveRecord::Schema[7.2].define(version: 2024_10_29_012413) do # These are extensions that must be enabled in order to support this database + enable_extension "pg_stat_statements" enable_extension "plpgsql" create_table "active_storage_attachments", force: :cascade do |t| @@ -50,6 +51,38 @@ t.index ["survey_response_id"], name: "index_annotations_on_survey_response_id" end + create_table "contexts", force: :cascade do |t| + t.string "name" + t.string "display_name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "questions", force: :cascade do |t| + t.string "key" + t.string "label" + t.boolean "is_experience", default: false + t.boolean "is_identity", default: false + t.boolean "is_feeling", default: false + t.boolean "is_affinity", default: false + t.boolean "is_reflection", default: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "context_id" + t.index ["context_id"], name: "index_questions_on_context_id" + end + + create_table "responses", force: :cascade do |t| + t.text "value" + t.string "raw_codes", default: [], array: true + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "question_id", null: false + t.bigint "survey_response_id", null: false + t.index ["question_id"], name: "index_responses_on_question_id" + t.index ["survey_response_id"], name: "index_responses_on_survey_response_id" + end + create_table "survey_responses", force: :cascade do |t| t.boolean "finished" t.text "age_given" @@ -104,4 +137,7 @@ add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "annotations", "survey_responses" + add_foreign_key "questions", "contexts" + add_foreign_key "responses", "questions" + add_foreign_key "responses", "survey_responses" end