我正在构建一个需要支持重复事件的组日历应用程序,但是我提出来处理这些事件的所有解决方案看起来都像是一个黑客.我可以限制前方可以看到的距离,然后立即生成所有事件.或者我可以将事件存储为重复,并在日历上向前看时动态显示它们,但如果有人想要更改特定事件实例的详细信息,我将不得不将它们转换为正常事件.
我确信有更好的方法可以做到这一点,但我还没有找到它.对重复事件建模的最佳方法是什么,您可以在其中更改特定事件实例的详细信息或删除特定事件实例?
(我正在使用Ruby,但请不要让这限制你的答案.如果有一个特定于Ruby的库或其他东西,那么,这很有用.)
我将对所有未来的重复事件使用"链接"概念.它们动态显示在日历中并链接回单个参考对象.当事件发生时,链接被破坏,事件变为独立实例.如果您尝试编辑定期事件,则提示更改所有将来的项目(即更改单个链接引用)或仅更改该实例(在这种情况下将其转换为独立实例,然后进行更改).由于您需要跟踪转换为单个实例的所有未来事件的重复列表,因此后者的问题稍有问题.但是,这完全是可行的.
因此,实质上,有两类事件 - 单个实例和重复事件.
Martin Fowler - Calendars的重复活动包含一些有趣的见解和模式.
Runt gem实现了这种模式.
重复发生的事件可能会有很多问题,让我重点介绍一下我所知道的事件.
存储原始约会+重复数据,不存储所有实例.
问题:
您需要在需要时计算日期窗口中的所有实例,成本高昂
无法处理异常(即,您删除其中一个实例,或移动它,或者更确切地说,您不能使用此解决方案执行此操作)
存储1中的所有内容,但也存储所有实例,链接回原始约会.
问题:
占用了大量空间(但空间很便宜,很小)
必须优雅地处理异常,特别是如果您在发出异常后返回并编辑原始约会.例如,如果您向前移动第三个实例,如果您返回并编辑原始约会的时间,在原始日期重新插入另一个并离开移动的约会,该怎么办?取消移动的移动链接?尝试适当更改移动的?
当然,如果你不打算做例外,那么任何一个解决方案都应该没问题,你基本上可以选择时间/空间权衡方案.
您可能希望查看iCalendar软件实现或标准本身(RFC 2445 RFC 5545).Mozilla项目很快就会浮现在脑海中http://www.mozilla.org/projects/calendar/ 快速搜索显示http://icalendar.rubyforge.org/.
可以考虑其他选项,具体取决于您将如何存储事件.您是否正在构建自己的数据库架构?使用基于iCalendar的东西等?
我正在使用以下内容:
http://github.com/elevation/event_calendar - 日历的模型和帮助程序
http://github.com/seejohnrun/ice_cube - 令人敬畏的经常性宝石
http://github.com/justinfrench/formtastic - 简单的表格
还有一个正在进行的宝石,它使用输入类型扩展了formtastic:recurring(form.schedule :as => :recurring
),它呈现类似iCal的界面,before_filter
并将视图IceCube
再次序列化为一个对象,ghetto-ly.
我的想法是让向模型添加重复属性并在视图中轻松连接它变得难以置信.一切都在几行.
那给了我什么呢?索引,可编辑,重复属性.
events
存储单日实例,并在日历视图/帮助器中使用,例如task.schedule
存储yaml'd IceCube
对象,因此您可以执行以下调用:task.schedule.next_suggestion
.
回顾:我使用两个模型,一个平面,用于日历显示,一个属性用于功能.
我开发了多个基于日历的应用程序,还编写了一组支持重复发生的可重用JavaScript日历组件.我写了一篇关于如何设计可能对某人有帮助的重现的概述.虽然有一些特定于我编写的库的位,但提供的绝大多数建议对于任何日历实现都是通用的.
一些关键点:
使用iCal RRULE格式存储重复- 这是你真正不想重新发明的一个轮子
不要将单个定期事件实例存储为数据库中的行!始终存储重复发生模式.
有许多方法可以设计事件/异常模式,但提供了一个基本的起点示例
所有日期/时间值都应以UTC格式存储并转换为本地值以供显示
为周期性事件存储的结束日期应始终为重复范围的结束日期(如果"永久"重复,则应为平台的"最大日期"),并且事件持续时间应单独存储.这是为了确保以后查询事件的理智方式.
包括有关生成事件实例和重复编辑策略的一些讨论
这是一个非常复杂的主题,有很多很多有效的方法来实现它.我会说我实际上已经多次成功实施了复发,而且我会警惕从没有实际做过这个问题的人那里接受这个问题的建议.
我正在使用如下所述的数据库模式来存储重复参数
http://github.com/bakineggs/recurring_events_for
然后我用runt动态计算日期.
https://github.com/mlipper/runt
跟踪重复规则(可能基于iCalendar,基于@ Kris K.)。这将包括模式和范围(每第三个星期二,出现10次)。
因为当你想编辑/删除发生的特定事件,追踪例外日期为上述复发规则(日期该事件不会发生因为规则规定)。
如果删除了,那就足够了,如果您进行编辑,则可以创建另一个事件,并将其父ID设置为主要事件。您可以选择是在该记录中包括所有主事件的信息,还是仅保留更改并继承所有未更改的信息。
请注意,如果您允许不终止的重复规则,则必须考虑如何显示现在无限量的信息。
希望有帮助!