From 0cdf38fcc0288a47a83705b65aaaef7bad016703 Mon Sep 17 00:00:00 2001 From: Jared Cosulich Date: Tue, 7 Mar 2017 12:40:09 -0500 Subject: [PATCH] testing scheduling --- Gemfile | 1 + Gemfile.lock | 2 + app/models/attempt.rb | 8 +++ app/models/recipient.rb | 2 + app/models/recipient_schedule.rb | 29 +++++++++ ...170307152229_create_recipient_schedules.rb | 13 ++++ db/migrate/20170307153205_create_attempts.rb | 17 ++++++ db/schema.rb | 26 +++++++- spec/models/attempt_spec.rb | 5 ++ spec/models/recipient_schedule_spec.rb | 61 +++++++++++++++++++ 10 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 app/models/attempt.rb create mode 100644 app/models/recipient_schedule.rb create mode 100644 db/migrate/20170307152229_create_recipient_schedules.rb create mode 100644 db/migrate/20170307153205_create_attempts.rb create mode 100644 spec/models/attempt_spec.rb create mode 100644 spec/models/recipient_schedule_spec.rb diff --git a/Gemfile b/Gemfile index e3eee649..89ff128c 100644 --- a/Gemfile +++ b/Gemfile @@ -74,6 +74,7 @@ group 'test' do gem 'poltergeist' gem 'launchy' gem 'database_cleaner' + gem 'timecop' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem diff --git a/Gemfile.lock b/Gemfile.lock index 6d37b29f..e0b0652d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -211,6 +211,7 @@ GEM thor (0.19.4) thread_safe (0.3.6) tilt (2.0.6) + timecop (0.8.1) turbolinks (5.0.1) turbolinks-source (~> 5) turbolinks-source (5.0.0) @@ -263,6 +264,7 @@ DEPENDENCIES spring spring-watcher-listen (~> 2.0.0) therubyracer + timecop turbolinks (~> 5) tzinfo-data uglifier (>= 1.3.0) diff --git a/app/models/attempt.rb b/app/models/attempt.rb new file mode 100644 index 00000000..bf1e9b25 --- /dev/null +++ b/app/models/attempt.rb @@ -0,0 +1,8 @@ +class Attempt < ApplicationRecord + + belongs_to :schedule + belongs_to :recipient + belongs_to :recipient_schedule + belongs_to :question + +end diff --git a/app/models/recipient.rb b/app/models/recipient.rb index 2ab7b684..be654c6a 100644 --- a/app/models/recipient.rb +++ b/app/models/recipient.rb @@ -4,6 +4,8 @@ class Recipient < ApplicationRecord belongs_to :school validates_associated :school + has_many :attempts + validates :name, presence: true def self.import(school, file) diff --git a/app/models/recipient_schedule.rb b/app/models/recipient_schedule.rb new file mode 100644 index 00000000..c2b59f92 --- /dev/null +++ b/app/models/recipient_schedule.rb @@ -0,0 +1,29 @@ +class RecipientSchedule < ApplicationRecord + + belongs_to :recipient + belongs_to :schedule + has_many :attempts + + def next_question + upcoming = upcoming_question_ids.split(/,/) + Question.where(id: upcoming.first).first + end + + def make_attempt(question: next_question) + sent_at = Time.new + recipient.attempts.create( + schedule: schedule, + recipient_schedule: self, + question: question, + sent_at: sent_at + ) + + upcoming = upcoming_question_ids.split(/,/)[1..-1].join(',') + attempted = (attempted_question_ids.split(/,/) + [question.id]).join(',') + update_attributes( + upcoming_question_ids: upcoming, + attempted_question_ids: attempted, + last_attempt_at: sent_at + ) + end +end diff --git a/db/migrate/20170307152229_create_recipient_schedules.rb b/db/migrate/20170307152229_create_recipient_schedules.rb new file mode 100644 index 00000000..713aa72b --- /dev/null +++ b/db/migrate/20170307152229_create_recipient_schedules.rb @@ -0,0 +1,13 @@ +class CreateRecipientSchedules < ActiveRecord::Migration[5.0] + def change + create_table :recipient_schedules do |t| + t.integer :recipient_id + t.integer :schedule_id + t.text :upcoming_question_ids + t.text :attempted_question_ids + t.timestamp :last_attempt_at + + t.timestamps + end + end +end diff --git a/db/migrate/20170307153205_create_attempts.rb b/db/migrate/20170307153205_create_attempts.rb new file mode 100644 index 00000000..c88bf8f1 --- /dev/null +++ b/db/migrate/20170307153205_create_attempts.rb @@ -0,0 +1,17 @@ +class CreateAttempts < ActiveRecord::Migration[5.0] + def change + create_table :attempts do |t| + t.integer :recipient_id + t.integer :schedule_id + t.integer :recipient_schedule_id + t.timestamp :sent_at + t.timestamp :responded_at + t.integer :question_id + t.integer :translation_id + t.integer :answer_index + t.integer :open_response_id + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 65eb6796..39ec57cb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,25 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170306145359) do +ActiveRecord::Schema.define(version: 20170307153205) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "attempts", force: :cascade do |t| + t.integer "recipient_id" + t.integer "schedule_id" + t.integer "recipient_schedule_id" + t.datetime "sent_at" + t.datetime "responded_at" + t.integer "question_id" + t.integer "translation_id" + t.integer "answer_index" + t.integer "open_response_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "categories", force: :cascade do |t| t.string "name" t.string "blurb" @@ -62,6 +76,16 @@ ActiveRecord::Schema.define(version: 20170306145359) do t.index ["school_id"], name: "index_recipient_lists_on_school_id", using: :btree end + create_table "recipient_schedules", force: :cascade do |t| + t.integer "recipient_id" + t.integer "schedule_id" + t.text "upcoming_question_ids" + t.text "attempted_question_ids" + t.datetime "last_attempt_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "recipients", force: :cascade do |t| t.string "name" t.string "phone" diff --git a/spec/models/attempt_spec.rb b/spec/models/attempt_spec.rb new file mode 100644 index 00000000..33640892 --- /dev/null +++ b/spec/models/attempt_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Attempt, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/recipient_schedule_spec.rb b/spec/models/recipient_schedule_spec.rb new file mode 100644 index 00000000..0fdc9580 --- /dev/null +++ b/spec/models/recipient_schedule_spec.rb @@ -0,0 +1,61 @@ +require 'rails_helper' + +RSpec.describe RecipientSchedule, type: :model do + + let(:question) { Question.create!(text: 'What is the question?', option1: 'A', option2: 'B', option3: 'C', option4: 'D', option5: 'E')} + let(:question_list) { QuestionList.create(name: 'Parent Questions', question_ids: "#{question.id},2,3")} + + let(:recipient) { Recipient.create!(name: 'Parent') } + let(:recipient_list) { RecipientList.create(name: 'Parent List', recipient_ids: recipient.id.to_s)} + + let(:schedule) { Schedule.create!(name: 'Parent Schedule', recipient_list_id: recipient_list.id, question_list: question_list) } + + let!(:recipient_schedule) do + RecipientSchedule.create!( + recipient: recipient, + schedule: schedule, + upcoming_question_ids: "#{question.id},3", + attempted_question_ids: '2', + last_attempt_at: 2.weeks.ago + ) + end + + describe 'next_question' do + it 'should provide the next question from the upcoming_question_ids list' do + expect(recipient_schedule.next_question).to eq(question) + end + end + + describe 'make_attempt' do + before :each do + Timecop.freeze + recipient_schedule.make_attempt + end + + it 'should contact the twillio API' + + it 'should make an attempt to ask the next question' do + expect(Attempt.count).to eq(1) + attempt = Attempt.first + expect(attempt.recipient).to eq(recipient) + expect(attempt.schedule).to eq(schedule) + expect(attempt.recipient_schedule).to eq(recipient_schedule) + expect(attempt.question).to eq(question) + expect(attempt.sent_at.to_i).to eq(Time.new.to_i) + expect(attempt.answer_index).to be_nil + end + + it 'should update the upcoming_questions_ids' do + expect(recipient_schedule.upcoming_question_ids).to eq('3') + end + + it 'should update the attempted_question_ids' do + expect(recipient_schedule.attempted_question_ids).to eq("2,#{question.id}") + end + + it 'should update last_attempt_at' do + expect(recipient_schedule.last_attempt_at.to_i).to eq(Time.new.to_i) + end + + end +end