以下是我的建模方法。我对Google日历的使用不多,因此我基于iCal的重复事件功能来设计这个模型。
所有模型都应该有常见的id、created_at和updated_at属性。下面是自定义属性列表。如果属性是另一个模型,则需要使用诸如has_one
或belongs_to
的关联方式来实现。
RecurrencePeriod
Event
base_event # has_one :base_event, :class_name'Event'
Time
end_date # 可能为nil,如果永久重复
WeeklyRecurrence
recurrence # has_one :recurrence, :as=>:recurrence
Array[OccurrenceOverride]
overrides # has_many :overrides, :class_name=>'OccurrenceOverride'
RecurrencePeriod
从其base_event
开始的日期开始。同时,我假设Event
的employee_id
指的是创建该事件的员工。一个RecurrencePeriod
也将属于创建base_event
的员工。
该模型取决于您希望指定重复次数的灵活性。您是要支持“每两周的周二和周四上午10点到11点,下午2点到3点”还是只支持“每周重复”?这里的模型仅支持“每周重复”,“每两周重复”等;如果需要,可以进行扩展。
WeeklyRecurrence
Integer
weeks_between_recurrences
RecurrencePeriod
recurrence_period # belongs_to :recurrence, :polymorphic=>true
我在这里使用多态关联,因为如果您想要多个类型的重复,如WeeklyRecurrence
和DailyRecurrence
,它们可能很有用。但我不确定这是否是正确的建模方式,所以如果它们不是,只需改用has_one:weekly_recurrence
和belongs_to:recurrence_period
。
Ice cube库似乎可以用于计算重复。如果上面的WeeklyRecurrence
不够强大,您可能只需在模型中存储一个Ice Cube Schedule
对象,取代WeeklyRecurrence
。要将Schedule
对象存储在模型中,请将其保存为属性"schedule",将serialize: schedule
放在模型定义中,并在数据库中生成文本列"schedule"。
OccurrenceOverride
处理编辑正在重复的事件的单个实例的情况。
OccurrenceOverride
RecurrencePeriod
recurrence_period_to_override # belongs_to :recurrence_period_to_override, :class_name=>'RecurrencePeriod'
Time
original_start_time # 唯一标识要替换的那个RecurrencePeriod内的重复
Event
replacement_event # has_one :replacement_event, :class_name=>'Event'
; 如果删除了该重复,则可能为nil
不必单独存储每个事件的出现,只需在需要在视图中显示它们时临时生成。在RecurrencePeriod
中创建一个方法generate_events_in_range(start_date, end_date)
,生成Event
并不保存到数据库,仅用于传递给视图以便展示。
当用户编辑重复事件时,应该有选择修改所有事件、所有未来事件或仅该事件的选项。如果他们修改了所有事件,则修改RecurrencePeriod
的基础事件。如果他们修改所有未来事件,则使用您应该在RecurrencePeriod
上实现的一种方法将其拆分为两个在某个日期之前和之后的RecurrencePeriod
,然后仅保存更改到第二个期间。如果他们仅修改该事件,则为他们要覆盖的时间创建一个OccurrenceOverride
,并将更改保存到覆盖的替换事件中。
当用户表示某个事件现在应该每两周重复一次,可以创建一个新的RecurrencePeriod
,该事件作为基础事件,无结束日期。其重复应为新的WeeklyRecurrence
,其中weeks_between_recurrence=2,并且不应该有任何OccurrenceOverride
。
OccurrenceOverride
在概念上非常相似,尽管并不完全相同。 - Rory O'Kane