28

我正在寻找对重复事件建模的最佳方法。我正在使用 fullcalendar 来显示事件。但我想最好在 Rails 后端处理重复发生的事件。

我已经查看了其他问题和现有的示例代码,但我没有找到任何合适的东西。

它的行为应该类似于谷歌日历。所以应该可以删除/修改重复事件系列的单个事件。但是将事件系列的所有事件保存在数据库中似乎效率低下。此外,应该可以创建单个事件而不会重复发生。

什么是好的模型架构?

我的事件模型现在看起来像这样(没有附加属性):

# Table name: events
#
#  id              :integer         not null, primary key
#  employee_id     :integer
#  created_at      :datetime
#  updated_at      :datetime
#  starts_at       :datetime
#  ends_at         :datetime
#

class Event < ActiveRecord::Base
  attr_accessible :starts_at, :ends_at
end
4

4 回答 4

42

这是我将如何建模。我没有太多使用 Google 日历,因此我将功能基于iCal的重复事件。

所有模型都应该具有通常的 id、created_at、updated_at 属性。列出的是自定义属性。如果该属性是另一个模型,您将实现它的关联,例如has_oneor belongs_to

  • RecurrencePeriod
    • Eventbase_event #has_one :base_event, :class_name'Event'
    • Timeend_date # 可能为 nil,如果它永远重复
    • WeeklyRecurrence复发#has_one :recurrence, :as=>:recurrence
    • Array[OccurrenceOverride]覆盖#has_many :overrides, :class_name=>'OccurrenceOverride'

RecurrencePeriod开始于其 base_event 开始的日期。另外,我假设 anEvent的 employee_id 是指创建该事件的员工。ARecurrencePeriod也将属于创建 base_event 的员工。

该模型取决于您希望能够灵活地指定重复次数。您是要支持“每周二和周四,从上午 10 点到上午 11 点,从下午 2 点到下午 3 点”还是只支持“每周重复一次”?这是一个只支持“每周重复”、“每两周重复”等的模型;如果需要,您可以扩展它。

  • WeeklyRecurrence
    • Integerweek_between_recurrences
    • RecurrencePeriod复发周期#belongs_to :recurrence, :polymorphic=>true

我在这里使用多态关联,因为我认为如果你想要不止一种类型的重复,它们可能很有用,比如WeeklyRecurrenceDailyRecurrence。但我不确定它们是否是建模的正确方法,所以如果结果不是,只需使用has_one :weekly_recurrenceandbelongs_to :recurrence_period代替。

Ice cube库似乎对计算重复率很有用。如果WeeklyRecurrence上面的功能不够强大,您可能只想Schedule在模型中存储一个冰块对象,替换WeeklyRecurrence. 要将Schedule对象存储在模型中,将其保存为属性“schedule”,放入serialize :schedule模型定义,并在数据库中生成文本列“schedule”。

OccurrenceOverride处理正在编辑的重复事件的单个实例的情况。

  • OccurrenceOverride
    • RecurrencePeriod重复周期到覆盖#belongs_to :recurrence_period_to_override, :class_name=>'RecurrencePeriod'
    • Timeoriginal_start_time # 唯一标识要替换该 RecurrencePeriod 中的哪个重复
    • Event替换事件# has_one :replacement_event, :class_name=>'Event'; 可能为零,如果该重复被删除而不是编辑

与其单独存储每个事件的发生,不如在需要在视图中显示它们时临时生成它们。在RecurrencePeriod中,创建一个generate_events_in_range(start_date, end_date)生成Events 的方法,而不是保存在数据库中,而只是传递给视图以便它可以显示它们。

当用户编辑重复时,他们应该可以选择修改所有事件、所有未来事件或仅修改该事件。如果他们修改了所有事件,请修改RecurrencePeriod'base_event. 如果他们修改了所有未来的事件,请使用您应该实施的方法,在特定日期的两侧RecurrencePeriod将自身拆分为两个s,然后将更改保存到第二个期间。如果他们仅修改该事件,则为他们覆盖的时间RecurrencePeriod创建一个,并将更改保存到覆盖的 replacement_event。OccurrenceOverride

当用户说某个事件现在应该在可预见的未来每两周重复一次时,您应该创建一个新RecurrencePeriod事件,该事件作为 base_event 和一个 nil end_date。它的重复周期应该是一个新WeeklyRecurrence的,weeks_between_recurrence=2,它应该没有OccurrenceOverrides。

于 2012-04-22T08:36:04.657 回答
6

就我而言,我做了这样的事情:

# Holds most of my event's data; name, description, price ...
class Event < ActiveRecord::Base
  has_many :schedules
  has_many :occurrences
  attr_accessible :started_at, :expired_at # expired_at is optional
end

# Holds my schedule object
class Schedule < ActiveRecord::Base
  belongs_to :event
  attr_accessible :ice_cube_rule # which returns my deserialized ice_cube object
end

# Holds generated or manually created event occurrences 
class Occurrence < ActiveRecord::Base
  belongs_to :event
  attr_accessible :started_at, :expired_at
  attr_accessible :generated # helps me tell which occurrences are out of an ice_cube generated serie
  attr_accessible :canceled_at
end

从那里,我使用ice_cube来管理出现次数计算并将结果存储在出现次数表中。我首先尝试在不使用 Occurrence 模型的情况下工作,但无论规则引擎多么先进,总会有例外情况,因此将出现次数存储在它们自己的模型中会给您带来灵活性。

拥有一个 Occurrence 模型可以更轻松地在日历上显示事件或使用日期搜索过滤器,因为您只需要查询事件然后显示相关事件的数据,而不是收集给定日期范围内的所有事件然后拥有过滤掉时间表不匹配的事件。

您还可以将事件发生标记为已取消或修改它(将生成的属性设置为 false,以便在编辑 ice_cube 时间表时不会清理它......或您的业务需要的任何东西)

当然,如果您有无限期重复的事件,您将希望限制您希望在未来多长时间内生成这些事件,并使用自动 rake 任务来清理旧事件并生成明年左右的事件。

到目前为止,这种模式对我来说效果很好。

另外,看看recurring_select gem,它是一个非常简洁的 ice_cube 表单输入。

于 2014-01-30T01:18:00.150 回答
4

只是我头脑中的一个观点,也许评论者会指出我目前没有想到的问题:

我会制作一个RecurringEvent模型(或任何你想称呼的模型)has_many :events

假设每个事件都是由员工(根据您的笔记)创建的,RecurringEvent那么belong_to :employee. 然后,您可以建立一种has_many :through关系,其中员工有许多事件并且有许多重复事件。

RecurringEvent 模型可以有一个开始日期和一个模式,它最初可以使用这个模式来创建各个发生的事件。然后,对于属于重复系列的任何事件,您可以修改或删除该单个事件,但您也可以“重新生成系列”,删除系列中的所有事件(或系列中的所有未来事件)并重建它们基于一种新的模式,例如将会议从“每个星期二”更改为“每个星期四”。

关于此的另一种好处是您可以创建一个重复事件的一览表,这可能会让您对人们的主要义务有一些很好的了解。

就像我说的那样,我想这就是我的方法,但这只是一个想法,我还没有建立任何类似的东西,所以我不知道我的方法是否有什么大问题建议。

祝你好运,请发布你最终做了什么!

于 2012-04-15T02:59:13.400 回答
-1

我对 Rails 很陌生,您的解决方案听起来很有趣。要创建计划和相关事件,您是否在事件模型中使用条件回调?

就我而言,用户将能够创建事件,无论是否每周重复。所以我在考虑事件模型中的一个循环布尔字段。所以我想你会有一个第一个回调来创建时间表:

before_save :create_weekly_schedule, if: :recurring

基本上是第二个来创建事件:

after_save :create_occurences_if_recurring

def create_occurences_if_recurring
  schedules.each do |sched|
    occurences.create(start_date: sched.start_time, end_date: sched.end_time)
  end
end

这听起来与您的解决方案合乎逻辑吗?谢谢

于 2014-05-16T23:07:57.300 回答