Получить меняющегося пользователя для правила повторения 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(&: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

person Gurpreet Dhaliwal    schedule 25.10.2020    source источник


Ответы (1)


Вы автоматически увеличиваете значение приоритета пользователей, верно?

schedule.schedule_users.rotate.each_with_index do |schedule_user, index|
  schedule_user.update(priority: num_users - index)
end

Итак, с 4 пользователями у вас должно быть что-то вроде этого в первый день:

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 x дней в будущем

Уравнение для расчета этого может быть:

priority = x.remainder(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
person Chiperific    schedule 26.10.2020