I\'m building a group calendar application that needs to support recurring events, but all the solutions I\'ve come up with to handle these events seem like a hack. I can li
I would use a 'link' concept for all future recurring events. They are dynamically displayed in the calendar and link back to a single reference object. When events have taken place the link is broken and the event becomes a standalone instance. If you attempt to edit a recurring event then prompt to change all future items (i.e. change single linked reference) or change just that instance (in which case convert this to a standalone instance and then make change). The latter cased is slightly problematic as you need to keep track in your recurring list of all future events that were converted to single instance. But, this is entirely do-able.
So, in essence, have 2 classes of events - single instances and recurring events.
Check the article below for three good ruby date/time libraries. ice_cube in particular seems a solid choice for recurrence rules and other stuff that an event calendar would need. http://www.rubyinside.com/3-new-date-and-time-libraries-for-rubyists-3238.html
Store the events as repeating and dynamically display them, however allow the recurring event to contain a list of specific events that could override the default information on a specific day.
When you query the recurring event it can check for a specific override for that day.
If a user makes changes, then you can ask if he wants to update for all instances (default details) or just that day (make a new specific event and add it to the list).
If a user asks to delete all recurrences of this event you also have the list of specifics to hand and can remove them easily.
The only problematic case would be if the user wants to update this event and all future events. In which case you'll have to split the recurring event into two. At this point you may want to consider linking recurring events in some way so you can delete them all.
I'm working with the following:
and a gem in progress that extends formtastic with an input type :recurring (form.schedule :as => :recurring
), which renders an iCal-like interface and a before_filter
to serialize the view into an IceCube
object again, ghetto-ly.
My idea is to make it incredibility easy to add recurring attributes to a model and connect it easily in the view. All in a couple of lines.
So what does this give me? Indexed, Edit-able, Recurring attributes.
events
stores a single day instance, and is used in the calendar view/helper
say task.schedule
stores the yaml'd IceCube
object, so you can do calls like : task.schedule.next_suggestion
.
Recap: I use two models, one flat, for the calendar display, and one attribute'd for the functionality.
I'd recommend using the power of the date library and the semantics of the range module of ruby. A recurring event is really a time, a date range (a start & end) and usually a single day of the week. Using date & range you can answer any question:
#!/usr/bin/ruby
require 'date'
start_date = Date.parse('2008-01-01')
end_date = Date.parse('2008-04-01')
wday = 5 # friday
(start_date..end_date).select{|d| d.wday == wday}.map{|d| d.to_s}.inspect
Produces all days of the event, including the leap year!
# =>"[\"2008-01-04\", \"2008-01-11\", \"2008-01-18\", \"2008-01-25\", \"2008-02-01\", \"2008-02-08\", \"2008-02-15\", \"2008-02-22\", \"2008-02-29\", \"2008-03-07\", \"2008-03-14\", \"2008-03-21\", \"2008-03-28\"]"
There can be many problems with recurring events, let me highlight a few that I know of.
Store original appointment + recurrence data, do not store all the instances.
Problems:
Store everything from 1, but also all the instances, linked back to the original appointment.
Problems:
Of course, if you're not going to do exceptions, then either solution should be fine, and you basically choose from a time/space trade off scenario.