I have an ice_cube recurrence rule, for example, which occurs daily. The objective of this rule is to rotate users on a daily basis.
For example, if I have 4 users: John, Peter, Mark, Matthew, and a daily recurrence rule. I also am using delayed jobs to create a single job to run on the next_occurence which will rotate the users in the schedule_users table (by changing a priority value). I am only creating one job at a time, for example when the first rotation is performed a new job will be created for the next occurrence.
I would like to see which of the users is scheduled for a particular day. How would I look ahead to see which users are scheduled for the next 3, 5, 7 etc or any number of days in the future.
class Schedule < ApplicationRecord
belongs_to :project
belongs_to :user
has_many :schedule_users, -> { order priority: :desc }, dependent: :destroy
has_many :users, through: :schedule_users
enum frequency: { daily: 0, weekly: 1, biweekly: 2, monthly: 3 }
validates_presence_of :name, :start, :frequency, :project
def next_occurrence
ice_cube_schedule.next_occurrence.start_time
end
def jobs
Delayed::Job.where('handler LIKE ?', "%Schedule/#{id}\%")
end
def on_call_user
schedule_users.max_by(&:priority).user if users.present?
end
def priority(user)
schedule_users.where(user: user).first.try(:priority)
end
def ice_cube_schedule
schedule = IceCube::Schedule.new(start, end_time: self.end)
case frequency
when 'daily'
schedule.add_recurrence_rule IceCube::Rule.daily(1)
when 'weekly'
schedule.add_recurrence_rule IceCube::Rule.weekly(1)
when 'biweekly'
schedule.add_recurrence_rule IceCube::Rule.weekly(2)
when 'monthly'
schedule.add_recurrence_rule IceCube::Rule.monthly(1)
end
schedule
end
end
class ScheduleUser < ApplicationRecord
belongs_to :schedule
belongs_to :user
validates_presence_of :priority, :schedule, :user
end
class ReprioritizeScheduleUsersJob < ApplicationJob
queue_as :default
after_perform do |job|
schedule = job.arguments.first
ReprioritizeScheduleUsersJob.set(wait_until: schedule.next_occurrence).perform_later(schedule)
end
def perform(schedule)
ActiveRecord::Base.transaction do
schedule_users = schedule.schedule_users.reload
num_users = schedule_users.count
schedule.schedule_users.rotate.each_with_index do |schedule_user, index|
schedule_user.update(priority: num_users - index)
end
end
end
end