Repository URL to install this package:
|
Version:
1.0.0.beta2 ▾
|
module Eventful
# Recurrence strategy for Events
class Schedule < ApplicationRecord
self.table_name = 'eventful_schedules'
before_validation :rebuild_program!
attr_reader :days_of_week, :recur_until
serialize :program, ::IceCube::Schedule
validates :start_time, :end_time, presence: true
validates_with RecurringTerminationValidator
validates_with EndAfterStartValidator
belongs_to :schedulable, polymorphic: true, touch: true
def program
self[:program] ||= ::IceCube::Schedule.new
end
def rebuild_program!
reset_program_rules!
if recurring?
self.program.add_recurrence_rule build_weekly_rule
end
self.program
end
def recurring?
days_of_week.present?
end
def terminating?
program.terminating?
end
def occurrences
program.all_occurrences
end
delegate :start_time, :end_time, to: :program
def start_time=(value)
program.start_time = parse_timeish(value, :start_time)
end
def end_time=(value)
program.end_time = parse_timeish(value, :end_time)
end
def recur_until
@recur_until ||= extract_recur_until(program)
end
def days_of_week
@days_of_week ||= extract_days_of_week(program)
end
def recur_until=(value)
@recur_until = parse_timeish(value, :recur_until)
end
def days_of_week=(days)
return [] if days.nil?
@days_of_week = days.reject(&:blank?).map(&:to_i)
end
private
def build_weekly_rule
unless days_of_week.empty?
IceCube::Rule.weekly.day(*days_of_week).until(recur_until)
end
end
def reset_program_rules!
program.instance_variable_set(:@all_recurrence_rules, [])
end
# TODO: Extract the extractors?
def extract_recur_until(ice_cube_schedule)
ice_cube_schedule.recurrence_rules[0]&.validations&.dig(:until, 0)&.time
end
def extract_days_of_week(ice_cube_schedule)
return unless rule = ice_cube_schedule.recurrence_rules.first
day_validations = rule.validations.fetch(:day, [])
return [] if day_validations.empty?
day_validations.map(&:day)
end
def parse_timeish(value, field = :base)
begin
Time.zone.parse value.to_s
rescue ArgumentError
errors[field] << I18n.t('eventful.errors.invalid_time_format')
nil
end
end
end
end