Efficiently retrieving ice_cube schedules for a given time period

2.2k Views Asked by At

I'm looking into using Ice Cube https://github.com/seejohnrun/ice_cube for recurring events. My question is, if I then need to get any events that fall within a given time period (say, on a day or within a week), is there any better way than to loop through them all like this:

items = Records.find(:all)
items.each do |item|
  schedule = item.schedule
  if schedule.occurs_on?(Date.new)
      #if today is a recurrence, add to array
  end
end

This seems horribly inefficient but I'm not sure how else to go about it.

2

There are 2 best solutions below

2
John On

That's one approach - but what people do more often is end up denormalizing their schedules into a format that is conveniently queryable.

You may have a collection called something like ScheduleOccurrences - that you build each week / and then query that instead.

Its unfortunate it has to work this way, but sticking to the iCal way of managing schedules has led IceCube to need to format its data in certain ways (specifically ways that can line up with the requirements of the iCal RFC).

I've been doing some thinking recently about what a library would look like that shook away some of those restrictions, for greater flexibility like this - but its definitely still a bit off.

Hope this helps

1
babiesinspace On

I faced a similar problem and here was my approach:

Create a column on Event table to store the next occurrence date, and write a method which stores that value after_save. (method available through ice_cube. Perhaps index column too for faster querying.)

Then you can query the database for occurrences happening in the timeframe you need. See below:

Event.where(next_occurrence: Date.today.all_day)

Store EventOccurrences on a separate table.

Update the next_occurrence column for the rows returned to you by your query. Or something similar. This works for me because I'm running a daily job, so that update next_occurrence will run regularly. But you may need to tweak a bit.