#ruby-on-rails #ruby #ice-cube
#ruby-on-rails #ruby #ice-cube
Вопрос:
Например, у меня есть правило повторения ice_cube, которое происходит ежедневно. Целью этого правила является ежедневная ротация пользователей.
Например, если у меня 4 пользователя: Джон, Питер, Марк, Мэтью и правило ежедневного повторения. Я также использую отложенные задания для создания одного задания для запуска в next_occurence, которое будет вращать пользователей в таблице schedule_users (путем изменения значения приоритета). Я создаю только одно задание за раз, например, когда выполняется первое вращение, для следующего вхождения будет создано новое задание.
Я хотел бы видеть, какой из пользователей запланирован на определенный день. Как бы я посмотрел вперед, чтобы узнать, какие пользователи запланированы на следующие 3, 5, 7 и т.д. Или любое количество дней в будущем.
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(amp;: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
Ответ №1:
Вы автоматически увеличиваете значение приоритета пользователей, верно?
schedule.schedule_users.rotate.each_with_index do |schedule_user, index|
schedule_user.update(priority: num_users - index)
end
Итак, с 4 пользователями у вас должно быть что-то подобное в день 1:
ScheduleUser.all.pluck(:name, :priority)
[["Matthew", 1], ["Mark", 2], ["Luke", 3], ["John", 4]]
И на 2-й день:
ScheduleUser.all.pluck(:name, :priority)
[["Matthew", 2], ["Mark", 3], ["Luke", 4], ["John", 1]]
И на 3-й день:
ScheduleUser.all.pluck(:name, :priority)
[["Matthew", 3], ["Mark", 4], ["Luke", 1], ["John", 2]]
Итак, другой способ подумать о вашей проблеме — это колесо массива.
Если я пройду через этот массив X раз, где я приземлюсь?
Я знаю, что Мэтью сегодня № 1, где он будет через 2 дня? #3.
Вот наши переменные:
- x = количество дней в будущем, которое вы хотите предсказать
- priority_array_size = количество возможных приоритетов (4 в этом примере) и равно schedule_user.size
- current_priority = текущий приоритет schedule_user для schedule_user
- приоритет = приоритет для schedule_user x дней в будущем
Уравнение для вычисления этого может быть:
приоритет = x.остаток (priority_array_size) current_priority
Я бы предположил, что это метод ScheduleUser
:
class ScheduleUser < ApplicationRecord
belongs_to :schedule
belongs_to :user
validates_presence_of :priority, :schedule, :user
def priority_in_x_days(days_in_future)
days_in_future.remainder(ScheduleUser.all.size) priority
end
end