这是我将如何建模。我没有太多使用 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 重复# has_one :recurrence, :as=>:recurrence
-
Array[OccurrenceOverride] 覆盖 # has_many :overrides, :class_name=>'OccurrenceOverride'
RecurrencePeriod 在其 base_event 开始的日期开始。另外,我假设Event 的employee_id 指的是创建该事件的员工。 RecurrencePeriod 也将属于创建 base_event 的员工。
模型取决于您希望能够灵活地指定重复次数。您是要支持“每周二和周四,从上午 10 点到上午 11 点,从下午 2 点到下午 3 点”,还是只支持“每周重复一次”?这是一个只支持“每周重复”、“每两周重复”等的模型;如果需要,您可以扩展它。
-
WeeklyRecurrence
-
Integerweek_between_recurrences
-
RecurrencePeriodrecurrence_period # belongs_to :recurrence, :polymorphic=>true
我在这里使用polymorphic associations,因为我认为如果您想要不止一种重复类型,例如WeeklyRecurrence 和DailyRecurrence,它们可能会很有用。但我不确定它们是否是正确的建模方法,所以如果结果不是这样,请改用 has_one :weekly_recurrence 和 belongs_to :recurrence_period。
Ice cube 库似乎对计算重复率很有用。如果上面的WeeklyRecurrence 不够强大,您可能只想在模型中存储一个冰块Schedule 对象,替换WeeklyRecurrence。要将Schedule对象存储在模型中,将其保存为属性“schedule”,将serialize :schedule放入模型定义中,并在数据库中生成文本列“schedule”。
OccurrenceOverride 处理正在编辑重复事件的单个实例的情况。
-
OccurrenceOverride
-
RecurrencePeriodrecurrence_period_to_override # belongs_to :recurrence_period_to_override, :class_name=>'RecurrencePeriod'
-
Time original_start_time #唯一标识要替换该 RecurrencePeriod 中的哪个重复
-
Eventreplacement_event # has_one :replacement_event, :class_name=>'Event';可能为零,如果该重复被删除而不是编辑
不要单独存储每个事件的发生,而是在需要在视图中显示它们时临时生成它们。在RecurrencePeriod 中,创建一个方法generate_events_in_range(start_date, end_date) 生成Events,而不是保存在数据库中,而只是传递给视图以便它可以显示它们。
当用户编辑重复发生时,他们应该可以选择修改所有事件、所有未来事件或仅修改该事件。如果他们修改了所有事件,请修改 RecurrencePeriod 的 base_event。如果他们修改了所有未来发生的事件,请使用您应该在RecurrencePeriod 上实施的方法,该方法在某个日期的任一侧将自身拆分为两个RecurrencePeriods,然后将更改保存到第二个期间。如果他们只修改该事件,请为他们覆盖的时间创建一个OccurrenceOverride,并将更改保存到覆盖的替换事件。
当用户说某个事件现在应该在可预见的未来每两周重复一次时,您应该创建一个新的RecurrencePeriod,将该事件作为 base_event 和一个 nil end_date。它的重复周期应该是一个新的WeeklyRecurrence,并且weeks_between_recurrence=2,它应该没有OccurrenceOverrides。