From 1086ee8b1006c0f7d97f4f8b58c9a42fe095f6b7 Mon Sep 17 00:00:00 2001 From: Jared Cosulich Date: Thu, 9 Mar 2017 11:41:30 -0500 Subject: [PATCH] working on recipient_schedule syncing --- app/models/recipient_list.rb | 22 +++++++++++++++++- app/models/recipient_schedule.rb | 25 ++++++++++++++++++++- app/models/schedule.rb | 12 ++++------ spec/models/attempt_spec.rb | 3 ++- spec/models/recipient_list_spec.rb | 36 ++++++++++++++++++++++++++++-- 5 files changed, 85 insertions(+), 13 deletions(-) diff --git a/app/models/recipient_list.rb b/app/models/recipient_list.rb index 08faea8f..87ea2331 100644 --- a/app/models/recipient_list.rb +++ b/app/models/recipient_list.rb @@ -1,5 +1,6 @@ class RecipientList < ApplicationRecord belongs_to :school + has_many :schedules validates_associated :school validates :name, presence: true @@ -9,6 +10,8 @@ class RecipientList < ApplicationRecord before_validation :convert_recipient_id_array after_initialize :set_recipient_id_array + after_save :sync_recipient_schedules + def recipients recipient_id_array.collect { |id| school.recipients.where(id: id).first } end @@ -16,7 +19,7 @@ class RecipientList < ApplicationRecord private def convert_recipient_id_array - return if recipient_id_array.blank? + return if recipient_id_array.blank? || (recipient_ids_was != recipient_ids) self.recipient_ids = recipient_id_array.reject { |id| id.to_s.empty? }.join(',') end @@ -25,4 +28,21 @@ class RecipientList < ApplicationRecord self.recipient_id_array = recipient_ids.split(',').map(&:to_i) end + def sync_recipient_schedules + return unless recipient_ids_was.present? && recipient_ids_was != recipient_ids + old_ids = recipient_ids_was.split(/,/) + new_ids = recipient_ids.split(/,/) + (old_ids - new_ids).each do |deleted_recipient| + schedules.each do |schedule| + schedule.recipient_schedules.for(deleted_recipient).first.destroy + end + end + + (new_ids - old_ids).each do |new_recipient| + schedules.each do |schedule| + RecipientSchedule.create_for_recipient(new_recipient, schedule) + end + end + end + end diff --git a/app/models/recipient_schedule.rb b/app/models/recipient_schedule.rb index 35da6c0f..5cdb7ff1 100644 --- a/app/models/recipient_schedule.rb +++ b/app/models/recipient_schedule.rb @@ -6,9 +6,15 @@ class RecipientSchedule < ApplicationRecord validates_associated :recipient validates_associated :schedule + validates :next_attempt_at, presence: true scope :ready, -> { where('next_attempt_at <= ?', Time.new) } - scope :for, -> (recipient) { where(recipient_id: recipient.id) } + scope :for, -> (recipient_or_recipient_id) { + id = recipient_or_recipient_id.is_a?(Recipient) ? + recipient_or_recipient_id.id : + recipient_or_recipient_id + where(recipient_id: id) + } def next_question upcoming = upcoming_question_ids.split(/,/) @@ -35,4 +41,21 @@ class RecipientSchedule < ApplicationRecord end return attempt end + + def self.create_for_recipient(recipient_or_recipient_id, schedule, next_attempt_at=Time.new) + question_ids = schedule.question_list.question_ids.split(/,/) + question_ids = question_ids.shuffle if schedule.random? + + recipient_id = recipient_or_recipient_id.is_a?(Recipient) ? + recipient_or_recipient_id.id : + recipient_or_recipient_id + + schedule.recipient_schedules.create( + recipient_id: recipient_id, + upcoming_question_ids: question_ids.join(','), + next_attempt_at: next_attempt_at + ) + end + + end diff --git a/app/models/schedule.rb b/app/models/schedule.rb index 27665f3c..63c28276 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -10,19 +10,15 @@ class Schedule < ApplicationRecord after_create :create_recipient_schedules - scope :active, -> { where(active: true).where("start_date <= ? and end_date > ?", Date.today, Date.today) } + scope :active, -> { + where(active: true).where("start_date <= ? and end_date > ?", Date.today, Date.today) + } private def create_recipient_schedules recipient_list.recipients.each do |recipient| - question_ids = question_list.question_ids.split(/,/) - question_ids = question_ids.shuffle if random - recipient_schedules.create( - recipient: recipient, - upcoming_question_ids: question_ids.join(','), - next_attempt_at: Time.new - ) + RecipientSchedule.create_for_recipient(recipient, self) end end diff --git a/spec/models/attempt_spec.rb b/spec/models/attempt_spec.rb index 2524c2e8..189da831 100644 --- a/spec/models/attempt_spec.rb +++ b/spec/models/attempt_spec.rb @@ -22,7 +22,8 @@ RSpec.describe Attempt, type: :model do schedule: schedule, upcoming_question_ids: "#{question.id},3", attempted_question_ids: '2', - last_attempt_at: 2.weeks.ago + last_attempt_at: 2.weeks.ago, + next_attempt_at: Time.new ) end diff --git a/spec/models/recipient_list_spec.rb b/spec/models/recipient_list_spec.rb index b92a79ce..2c94106d 100644 --- a/spec/models/recipient_list_spec.rb +++ b/spec/models/recipient_list_spec.rb @@ -14,8 +14,40 @@ describe RecipientList do end describe "when edited" do - it 'should delete recipient_schedules if a recipient is removed' + let!(:school) { School.create!(name: 'School') } - it 'should create recipient_schedules if a recipient is added' + let!(:recipients) { create_recipients(school, 3) } + let!(:recipient_list) do + school.recipient_lists.create!(name: 'Parents', recipient_ids: recipients.map(&:id).join(',')) + end + + let!(:questions) { create_questions(3) } + let!(:question_list) do + QuestionList.create!(name: 'Parent Questions', question_ids: questions.map(&:id).join(',')) + end + + let!(:schedule) do + Schedule.create!( + name: 'Parent Schedule', + recipient_list_id: recipient_list.id, + question_list: question_list, + random: false, + frequency_hours: 24 * 7 + ) + end + + it 'should delete recipient_schedules if a recipient is removed' do + modified_recipient_ids = recipients.map(&:id)[0,2].join(',') + expect do + recipient_list.update_attributes(recipient_ids: modified_recipient_ids) + end.to change { schedule.recipient_schedules.count }.from(3).to(2) + end + + it 'should create recipient_schedules if a recipient is added' do + new_recipients = create_recipients(school, 2) + expect do + recipient_list.update_attributes(recipient_ids: (recipients + new_recipients).map(&:id).join(',')) + end.to change { schedule.recipient_schedules.count }.from(3).to(5) + end end end