В некоторых проектах требуется дать возможность пользователю настроить правила для повторяющихся событий. Иногда правила событий могут быть достаточно сложными, к примеру, “каждый предпоследний день месяца” или “каждую вторую пятницу месяца до определенной даты“. Для решения подобных задач можно успешно применять gem ice_cube.
Gem ice_cube позволяет задавать правила для повторяющихся событий используя API на подобие iCalendar и сериализовать/десериализовать расписания в форматах YAML и Ruby Hash. Ice_cube позволяет хранить только одно расписание, а не генерировать сразу сотни событий на перед. Мы выбрали ice_cube из-за удобного и гибкого API, постоянных обновлений и исправлений ошибок, популярности среди других разработчиков.
Инсталяция gem:
gem install ice_cube
Для создания расписания необходимо воспользоваться классом IceCube::Schedule:
require 'rubygems'
require 'ice_cube'
include IceCube
# Параметры:
# - дата/время начала расписания
# {
# :duration => 3600 - продолжительность в секундах
# :end_time => Time.now + 3600 - время окончания
# }
schedule = Schedule.new(Date.today)
# Добавить повторение
schedule.add_recurrence_time(Date.today)
# Добавить исключение
schedule.add_exception_time(Date.today + 1)
Для создания правил повторения служит класс IceCube::Rule. Ice_сube поддерживает правила для ежедневных, еженедельных, ежемесячных, ежегодных, ежечасных, ежеминутных и ежесекундных повторений. Несколько примеров использования (более полный список примеров можно найти на странице проекта):
# Каждый 4-ый день
schedule.add_recurrence_rule Rule.daily(4)
# Каждую вторую неделю, в понедельник и пятницу
schedule.add_recurrence_rule Rule.weekly(2).day(:monday, :friday)
# Ежемесячно 10, 20 числа, и в последний день месяца
schedule.add_recurrence_rule Rule.monthly.day_of_month(10, 20, -1)
# Каждый месяц, в первый понедельник и последний вторник
schedule.add_recurrence_rule Rule.monthly.day_of_week(
:monday => [1],
:tuesday => [-1]
)
# Каждый год, на 50 день и на 100 день с конца
schedule.add_recurrence_rule Rule.yearly.day_of_year(50, -100)
Несколько правил можно комбинировать в одном расписании, в том числе и исключающие правила:
# Каждый 4-ый день / исключая понедельники и пятницы
schedule.add_recurrence_rule Rule.daily(4)
schedule.add_exception_rule Rule.weekly.day(1, 5)
Для правил можно устанавливать ограничения по количеству повторов и до определенной даты:
# Каждый 2-ой день, десять раз
schedule.add_recurrence_rule Rule.daily(2).count(10)
# Каждый 2-ой день, до конца месяца
schedule.add_recurrence_rule Rule.daily(2).until(Date.today.next_month - Date.today.day)
Теперь, наверное, самое интересное — запросы к расписанию:
# Все случаи повторений
schedule.all_occurrences
# Все случаи повторений до определенного времени
schedule.occurrences((Date.today + 5).to_time)
# Произойдет в определенное время
schedule.occurs_at?(Time.now)
# Произойдет в определенный день
schedule.occurs_on?(Date.today)
# Произойдет в промежутке времени
schedule.occurs_between?(Time.now, (Date.today + 5).to_time)
# Первые случаи повторения
schedule.first
schedule.first(3)
# Следующий случий повторения
schedule.next_occurrence
# Следующие 3 случая повторения
schedule.next_occurrences(3)
# Оставшиеся случаи повторения
schedule.remaining_occurrences
Сериализация данных в форматы YAML/HASH/iCal:
# YAML
yaml = schedule.to_yaml
Schedule.from_yaml(yaml)
# Hash
hash = schedule.to_hash
Schedule.from_hash(hash)
# iCalendar
schedule.to_ical
Мы используем gem ice_cube для реализации календаря повторяющихся событий вместе с FullCalendar и DelayedJob, пример использования можно посмотреть на этой странице.
Некоторые примеры для этой статьи взяты из официальной документации. Если у Вас есть вопросы или замечания, буду рад на них ответить.
Ссылки:
github.com/seejohnrun/ice_cube — страница проекта на GitHub.
seejohnrun.github.com/ice_cube/static/ice_cube_ruby_nyc.pdf — презентация ice_cube.
seejohnrun.github.com/ice_cube/static/lsrc_ice_cube.pdf — еще одна презентация.
www.inexfinance.com/en/blog/2012/12/2/gem_ice_cube — английский вариант этой статьи.
github.com/inex-finance/blog-examples — примеры из данной статьи.
Автор: DeltaSpace