Reoccurring events with simple_calendar and ice_cube
I am developing a Rails app that has a
Task model. It's like any basic task tracking system where you can set some attributes (name, activity, status, priority etc.) and a due date. For my system I am sticking with just dates but I am actually going to use
datetime types to plan for the future if I change my mind.
Simple one-off tasks are easy but most you would want to re-occur. After a lot or Googling in my opinion the best Rails solution is ice_cube (https://github.com/seejohnrun/ice_cube) with recurring_select (https://github.com/GetJobber/recurring_select). recurring_select makes it dead simple to schedule complex repeating events and then use ice_cube to do all the heave lifting for the scheduling.
There are lots of calendars out there but as the name suggests simple_calendar seems to be an obvious choice. With most re-occuring calendars the issue is parsing the events in a time period. There is no really easy way to say find all your Tasks that fall in a window of time (for example a simple_calendar given month). You would end up needing to loop through ALL of your events for a given day and parse out the ones that fall on that day.
Here is my idea - with a given Task when you create up update the task there is a call back that creates / updates an
Event that for the most part is a simple model with a Task foreign key and a date. These
Task. There is one drawback I see. You would need to set a limit (say 10 years) to auto-generate
Events. It would seem trivial to also be able to set an update_date column based on the schedule that you could use on a nightly rake / sidekiq task to run though an regenerate more future events.
Now you can pass the Events.all or any other ransack search etc. into simple_calendar for display. You can then just call event.task.attribute to get the parent data.
For my system I want to have comments, attachments etc. for completed tasks. When an Event is completed the parent Task is cloned with the original being saved as the read-only record for the last Event and the new cloned Task would be set back to 'active' or some other status and the new Events generated from it. All these Tasks would have some sort of common UUID like the ancestry gem or something like that. You can then see the previous tasks history etc. For example in my case I would be tracking a cost component. You could then see a long term trend in the costs etc.
I want to keep this simple but I see some issues that could make this (and any other system) get ugly fast.
- re-scheduling future events
- removing single events
- changing the parent ice_cube rule and how to handle the two items above
Thoughts / comments / suggestions?
Did you end up coming with a solution? I'm interested to see what others have to say. It might be worth checking out the Google Calendar API handles recurring events: https://developers.google.com/google-apps/calendar/v3/reference/events
I have been chewing on this for a few days. I am thinking about it too much. If I read that link correctly they do it like I was planning. The event belongs to "recurringEventId". I am going to ignore the idea of removing single events, re-scheduling for now. I am going to get it up and running with a minimal feature set and then add those later (if I even need to).
I think I will have Events in one of 5 states:
- active (this is the next event in the queue)
- cancelled (for some reason you decided to not complete that occurrence)
- deferred (you still plan to complete it but the system will not remind you until the deferred date)
- planned (all events after the active one - just placeholder to fill the calendar
The Tasks then have perhaps have 3 states:
- open (the Events show in the calendar, reminders are sent etc.)
- paused (not sure on the Event logic here yet)
- closed (future Events are cleared etc.)