From 48eb55ad940d7a655b8ca5cc1db04620e1aa510a Mon Sep 17 00:00:00 2001 From: Jared Cosulich Date: Sun, 12 Mar 2017 21:04:40 -0400 Subject: [PATCH] working on aggregated results --- app/models/attempt.rb | 15 ++++++++ app/models/question.rb | 3 ++ app/models/recipient.rb | 2 ++ app/models/school_category.rb | 27 +++++++++++++++ ...20170312202259_create_school_categories.rb | 13 +++++++ db/schema.rb | 16 ++++++++- lib/tasks/data.rake | 2 +- spec/controllers/attempts_controller_spec.rb | 6 ++-- spec/lib/tasks/survey_rake_spec.rb | 5 +-- spec/models/school_category_spec.rb | 34 +++++++++++++++++++ spec/spec_helper.rb | 5 +-- 11 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 app/models/school_category.rb create mode 100644 db/migrate/20170312202259_create_school_categories.rb create mode 100644 spec/models/school_category_spec.rb diff --git a/app/models/attempt.rb b/app/models/attempt.rb index d20315e4..50819d4d 100644 --- a/app/models/attempt.rb +++ b/app/models/attempt.rb @@ -7,6 +7,11 @@ class Attempt < ApplicationRecord belongs_to :recipient_schedule belongs_to :question + after_save :update_school_categories + + scope :for_category, -> (category) { joins(:question).merge(Question.for_category(category)) } + scope :for_school, -> (school) { joins(:recipient).merge(Recipient.for_school(school)) } + def send_message twilio_number = ENV['TWILIO_NUMBER'] client = Twilio::REST::Client.new ENV['TWILIO_ACCOUNT_SID'], ENV['TWILIO_AUTH_TOKEN'] @@ -21,4 +26,14 @@ class Attempt < ApplicationRecord recipient.update_attributes(phone: client.messages.get(message.sid).to) end + private + + def update_school_categories + school_category = SchoolCategory.for(recipient.school, question.category).first + if school_category.nil? + school_category = SchoolCategory.create(school: recipient.school, category: question.category) + end + # school_category.aggregate_responses + end + end diff --git a/app/models/question.rb b/app/models/question.rb index 4b161268..8ad5c702 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -8,6 +8,9 @@ class Question < ApplicationRecord validates :option4, presence: true validates :option5, presence: true + scope :for_category, -> (category) { where(category: category) } + + def options [option1, option2, option3, option4, option5].map(&:downcase).map(&:strip) end diff --git a/app/models/recipient.rb b/app/models/recipient.rb index eb00de07..c5115fc7 100644 --- a/app/models/recipient.rb +++ b/app/models/recipient.rb @@ -8,6 +8,8 @@ class Recipient < ApplicationRecord validates :name, presence: true + scope :for_school, -> (school) { where(school: school) } + before_destroy :sync_lists def self.import(school, file) diff --git a/app/models/school_category.rb b/app/models/school_category.rb new file mode 100644 index 00000000..177c4933 --- /dev/null +++ b/app/models/school_category.rb @@ -0,0 +1,27 @@ +class SchoolCategory < ApplicationRecord + + belongs_to :school + belongs_to :category + + scope :for, -> (school, category) { where(school: school).where(category: category) } + + def aggregated_responses + attempt_data = Attempt. + for_category(category). + for_school(school). + select('count(attempts.id) as attempt_count'). + select('count(attempts.answer_index) as response_count'). + select('sum(attempts.answer_index) as answer_index_total')[0] + + return { + attempt_count: attempt_data.attempt_count, + response_count: attempt_data.response_count, + answer_index_total: attempt_data.answer_index_total + } + end + + def aggregate_responses + return if ENV['BULK_PROCESS'] + + end +end diff --git a/db/migrate/20170312202259_create_school_categories.rb b/db/migrate/20170312202259_create_school_categories.rb new file mode 100644 index 00000000..f311dc38 --- /dev/null +++ b/db/migrate/20170312202259_create_school_categories.rb @@ -0,0 +1,13 @@ +class CreateSchoolCategories < ActiveRecord::Migration[5.0] + def change + create_table :school_categories do |t| + t.references :school, foreign_key: true + t.references :category, foreign_key: true + t.integer :attempt_count + t.integer :response_count + t.integer :answer_index_total + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 6a03c630..fa14b561 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170311195824) do +ActiveRecord::Schema.define(version: 20170312202259) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -122,6 +122,18 @@ ActiveRecord::Schema.define(version: 20170311195824) do t.index ["school_id"], name: "index_schedules_on_school_id", using: :btree end + create_table "school_categories", force: :cascade do |t| + t.integer "school_id" + t.integer "category_id" + t.integer "attempt_count" + t.integer "response_count" + t.integer "answer_index_total" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["category_id"], name: "index_school_categories_on_category_id", using: :btree + t.index ["school_id"], name: "index_school_categories_on_school_id", using: :btree + end + create_table "schools", force: :cascade do |t| t.string "name" t.integer "district_id" @@ -149,4 +161,6 @@ ActiveRecord::Schema.define(version: 20170311195824) do add_foreign_key "recipient_lists", "schools" add_foreign_key "schedules", "schools" + add_foreign_key "school_categories", "categories" + add_foreign_key "school_categories", "schools" end diff --git a/lib/tasks/data.rake b/lib/tasks/data.rake index 5919fe6b..f842b129 100644 --- a/lib/tasks/data.rake +++ b/lib/tasks/data.rake @@ -202,6 +202,6 @@ namespace :data do end ENV.delete('BULK_PROCESS') - # SchoolMeasure.all.each { |sm| sm.calculate_measurements } + SchoolCategory.all.each { |sc| sc.aggregate_responses } end end diff --git a/spec/controllers/attempts_controller_spec.rb b/spec/controllers/attempts_controller_spec.rb index a7f938fa..b49a9120 100644 --- a/spec/controllers/attempts_controller_spec.rb +++ b/spec/controllers/attempts_controller_spec.rb @@ -5,9 +5,11 @@ RSpec.describe AttemptsController, type: :controller do let(:valid_session) { {} } let(:schedule) { Schedule.new } - let(:recipient) { Recipient.create(name: 'Recipient', phone: '+11231231234') } + let(:school) { School.create!(name: 'School') } + let(:recipient) { Recipient.create!(name: 'Recipient', phone: '+11231231234') } let(:recipient_schedule) { RecipientSchedule.new } - let(:question) { Question.new } + let(:category) { Category.create!(name: 'Category') } + let(:question) { create_questions(1, category).first } let!(:first_attempt) { Attempt.create( schedule: schedule, diff --git a/spec/lib/tasks/survey_rake_spec.rb b/spec/lib/tasks/survey_rake_spec.rb index 62445e05..ed14bb5a 100644 --- a/spec/lib/tasks/survey_rake_spec.rb +++ b/spec/lib/tasks/survey_rake_spec.rb @@ -29,7 +29,8 @@ describe "survey:attempt_questions" do school.recipient_lists.create!(name: 'Parents', recipient_ids: recipients.map(&:id).join(',')) end - let!(:questions) { create_questions(3) } + let!(:category) { Category.create(name: 'Category') } + let!(:questions) { create_questions(3, category) } let!(:question_list) do QuestionList.create!(name: 'Parent Questions', question_ids: questions.map(&:id).join(',')) end @@ -86,7 +87,7 @@ describe "survey:attempt_questions" do describe 'A Week Later' do before :each do - Timecop.freeze(Date.today + 8) { subject.invoke } + Timecop.freeze(Date.today + 10) { subject.invoke } end it 'should create the second attempt for each recipient with a different question' do diff --git a/spec/models/school_category_spec.rb b/spec/models/school_category_spec.rb new file mode 100644 index 00000000..bc6d3a2d --- /dev/null +++ b/spec/models/school_category_spec.rb @@ -0,0 +1,34 @@ +require 'rails_helper' + +RSpec.describe SchoolCategory, type: :model do + + let!(:school1) { School.create!(name: 'School 1') } + let!(:school2) { School.create!(name: 'School 2') } + + let!(:school1recipients) { create_recipients(school1, 4) } + let!(:school2recipients) { create_recipients(school2, 4) } + + let!(:category1) { Category.create!(name: 'Category 1') } + let!(:category2) { Category.create!(name: 'Category 2') } + + let!(:questions) { create_questions(3, category1) } + + let!(:attempt1) { Attempt.create(question: questions[0], recipient: school1recipients[0], answer_index: 2)} + let!(:attempt2) { Attempt.create(question: questions[0], recipient: school1recipients[1])} + let!(:attempt3) { Attempt.create(question: questions[0], recipient: school1recipients[2], answer_index: 3)} + let!(:attempt4) { Attempt.create(question: questions[0], recipient: school2recipients[0], answer_index: 4)} + + let!(:school_category) { SchoolCategory.for(school1, category1).first } + + describe 'aggregated_responses' do + it 'should provide the count and sum of all attempts' do + expect(school_category.aggregated_responses).to eq( + attempt_count: 3, + response_count: 2, + answer_index_total: 5 + ) + end + end + + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a5bff0f2..5966aa45 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -146,7 +146,7 @@ def create_recipients(school, count) return recipients end -def create_questions(count) +def create_questions(count, category=nil) questions = [] count.times do |i| questions << Question.create( @@ -155,7 +155,8 @@ def create_questions(count) option2: "Option #{i}:#{count} B", option3: "Option #{i}:#{count} C", option4: "Option #{i}:#{count} D", - option5: "Option #{i}:#{count} E" + option5: "Option #{i}:#{count} E", + category: category ) end return questions