Hiccup mixes a-la-cart recurrence features into your recurring model. It doesn't dictate the data structure of your model, just the interface. It works like Devise does for authenticatable models.
Hiccup does provide a lightweight Schedule
class that mixes in all of Hiccup's feature, but you don't have to use Hiccup's Schedule if you don't want to.
class Schedule
extend Hiccup
hiccup :enumerable,
:validatable,
:humanizable,
:inferable,
:serializable => [:ical]
end
Hiccup requires that a recurring object expose the following properties
- kind: one of
:never
,:weekly
,:monthly
,:annually
- start_date: the date when the recurrence should start
- ends: either
true
orfalse
, indicating whether the recurrence has an end date - end_date: the date when the recurrence should end
- skip: the number of instances to skip (You'd set
skip
to 2 to specify an event that occurs every other week, for example) - weekly_pattern: an array of weekdays on which a weekly event should recur
- monthly_pattern: an array of recurrence rules for a monthly event
# Every other Monday
Schedule.new(:kind => :weekly, :weekly_pattern => ["Monday"])
# Every year on June 21 (starting in 1999)
Schedule.new(:kind => :yearly, :start_date => Date.new(1999, 6, 21))
# The second and fourth Sundays of the month
Schedule.new(:kind => :monthly, :monthly_pattern => [[2, "Sunday"], [4, "Sunday"]])
Supplies methods for creating instances of a recurring pattern
Examples
schedule = Schedule.new(
:kind => :weekly,
:weekly_pattern => %w{Monday Wednesday Friday},
:start_date => Date.new(2009, 3, 15))
# includes?
schedule.includes? Date.new(2009, 5, 20) # => true
schedule.includes? Date.new(2009, 3, 15) # => false (3/15/09 is a Sunday)
# occurrences_between
schedule.occurrences_between(
Date.new(2009, 3, 26),
Date.new(2009, 3, 31)) #=> [Fri, 27 Mar 2009, Mon, 30 Mar 2009]
# n_occurrences_before
schedule.n_occurrences_before(3, Date.new(2009, 3, 31)) # => [Mon, 30 Mar 2009, Fri, 27 Mar 2009, Wed, 25 Mar 2009]
Mixes in ActiveModel validations for recurrence models
Represents a recurring pattern in a human-readable string
Examples:
# A monthly recurrence
schedule = Schedule.new(:kind => :monthly, :monthly_pattern => [[-1, "Tuesday"]])
schedule.humanize # => "The last Tuesday of every month"
# With skips
schedule = Schedule.new(:kind => :weekly, :weekly_pattern => %w[Sunday], :skip => 2)
schedule.humanize # => "Every other Sunday"
# An anniversary
schedule = Schedule.new(:kind => :annually, start_date: Date.new(2012, 10, 1))
schedule.humanize # => "Every year on October 1"
Infers a schedule from an array of dates
Examples:
schedule = Schedule.infer %w{2012-7-9 2012-8-13 2012-9-10}
schedule.humanize # => "The second Monday of every month"
schedule = Schedule.infer %w{2010-3-4 2011-3-4 2012-3-4}
schedule.humanize # => "Every year on March 4"
schedule = Schedule.infer %w{2012-3-6 2012-3-8 2012-3-15 2012-3-20 2012-3-27 2012-3-29}
schedule.humanize # => "Every Tuesday and Thursday"
Supports serializing and deserializing a recurrence pattern to an array of formats
Examples:
schedule = Schedule.from_ical <<-ICAL
DTSTART;VALUE=DATE-TIME:20090101T000000Z
RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH
ICAL
schedule.humanize # => "Tuesday and Thursday of every other week"
schedule = Schedule.new(
:kind => :weekly,
:weekly_pattern => %w{Tuesday Thursday},
:start_date => DateTime.new(2009, 1, 1),
:skip => 2)
schedule.to_ical # => "DTSTART;VALUE=DATE-TIME:20090101T000000Z\nRRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH\n"
Copyright (c) 2012 Bob Lail, released under the MIT license