I want to find a Ruby gem that can work with recurring events that satisfies the following requirements:
I found two relevant candidates:
Could you suggest a gem (or set of gems) and describe how well it (or they) meet the criteria listed?
(And if I've missed some important criteria, please mention them in your answer.)
I end up using Ice_Cube for the following reasons:
These on my criteria are not fullfilled by it:
This one is not verified:
Creating Ice_Cube::Schedule from user input in Rails is not very convinient, but doable:
class EntryForm < FormModel
include IceCube
class_eval &ValidatesTimelinessSupport[{:start_date => :datetime}]
Units = [Day = 'day', Week = 'week']
Intervals = %w[0 1 2 3 4 5 6 7 8 9]
Week_Days = [:sunday, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday]
Days_With_Letters = Week_Days.zip(%w[S M T W T F S])
attr_accessible_accessors :interval, :unit, :start_date
attr_accessible_accessors *Week_Days
def_delegators :@model, :display_title, :schedule_yaml, :schedule_yaml=
validates_date :start_date, :allow_blank => true
validates_inclusion_of :unit, :in => Units
validates_inclusion_of :interval, :in => Intervals
validates_inclusion_of :complete, :in => %w[0 1], :allow_blank => true
Week_Days.each { |day| validates_inclusion_of day, :in => %w[0 1], :allow_blank => true }
before_edit {
if not schedule_yaml.blank? and hash = YAML::load(schedule_yaml)
schedule = Schedule.from_hash(hash)
end
if schedule and rule = schedule.rrules.first
@start_date = schedule.start_date
rule_hash = rule.to_hash
@interval = rule_hash[:interval]
case rule
when DailyRule
@unit = Day
when WeeklyRule
@unit = Week
rule_hash[:validations][:day].try :each do |day_index|
send "#{Week_Days[day_index]}=", 1
end
end
else
@start_date = Date.today
@interval = 1
@unit = Day
end
}
before_save {
sd = @start_date.blank? ?
Date.today.to_all_day :
@start_date.parse_date_in_timezone
i = @interval.to_i
schedule = Schedule.new(sd)
rule = case @unit
when Day
Rule.daily i
when Week
Rule.weekly(i).day(
*Week_Days.
select { |day| send(day).to_i == 1 } )
end
schedule.add_recurrence_rule(rule)
self.schedule_yaml = schedule.to_yaml
end
}
end
As lovely as Ice_Cube is, it doesn't seem suitable for a large scale scheduling applications where you might have 100,000 + Events that you need to filter through to see what appears on a current day. Think meetup.com
Because it's all serialized into a rule string the only way to filter a major list seems to be something like this:
def self.entries_on(date)
entries = TimetableEntry.all
entries.reject{|te|!te.schedule.occurs_on?(date)}
end
Not very efficient. Someone PLEASE CORRECT ME!! hopefully I'm missing a trick?
Also try the above method with a Date that's 100 years in the future... it appears as though ice_cube slows down the further you query away from the current date.
I'm not aware of a single plugin that handles all of your requirements, but the combination of rufus-scheduler and chronic should get you pretty far.
Rufus scheduler handles scheduling using a cron-like format that also accommodates local timezones. Chronic does the natural language parsing. Putting them together should solve most of your needs.
The Rufus documentation has some notes on pairing the two solutions.
I recommend taking a look RubyToolbox's Recurring Events gems. It should be up to date and includes ice_cube, mentioned previously.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With