日历中的周期性事件 - 导轨
我正在寻找模拟周期性事件的最佳方法。我正在使用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
下面是我将如何建模。我还没有使用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 #可以是零,当它反复永远 -
WeeklyRecurrence
复发#has_one :recurrence, :as=>:recurrence
-
Array[OccurrenceOverride]
所覆盖#has_many :overrides, :class_name=>'OccurrenceOverride'
-
的RecurrencePeriod
开始在其base_event开始的日期。另外,我假定Event
的employee_id是指创建该事件的员工。 A RecurrencePeriod
也将属于创建base_event的员工。
该模型取决于您希望如何灵活指定重复。您是否打算支持“周二和周四每两周从早上10点到上午11点,从下午2点到下午3点”或者“每周重复”?这是一个支持“每周重复”,“每两周重复一次”的模型。如果需要,您可以扩展它。
-
WeeklyRecurrence
-
Integer
weeks_between_recurrences -
RecurrencePeriod
RECURRENCE_PERIOD #belongs_to :recurrence, :polymorphic=>true
-
我用polymorphic associations这里,因为我觉得他们可能是有用的,如果你想要更多的不是一个类型的复发,例如WeeklyRecurrence
和DailyRecurrence
。但我不确定他们是否是正确的模拟方式,所以如果他们不成立,只需使用has_one :weekly_recurrence
和belongs_to :recurrence_period
。
Ice cube库似乎可能对计算重现有用。如果上面的WeeklyRecurrence
功能不够强大,您可能只想在模型中存储冰块Schedule
对象,替换WeeklyRecurrence
。要将Schedule
对象存储在模型中,请将其保存为属性“计划”,将serialize :schedule
放入模型定义中,并在数据库中生成文本列“计划”。
OccurrenceOverride
处理正在编辑的重复事件的单个实例的情况。
-
OccurrenceOverride
-
RecurrencePeriod
recurrence_period_to_override #belongs_to :recurrence_period_to_override, :class_name=>'RecurrencePeriod'
-
Time
original_start_time#唯一地识别哪个那RecurrencePeriod内复发取代 -
Event
replacement_eventhas_one :replacement_event, :class_name=>'Event'
#;可能是零,如果复发被删除,而不是编辑
-
而是单独存储事件的每次出现的,暂时生成它们,当你需要向他们展示在视图中。在RecurrencePeriod
中,创建一个方法generate_events_in_range(start_date, end_date)
,该方法生成Event
,不保存在数据库中,而只是传递给视图以便显示它们。
当用户编辑重现时,他们应该可以选择修改所有出现次数,所有未来出现次数或仅该事件。如果他们修改所有事件,请修改RecurrencePeriod
的base_event。如果他们修改所有将来的事件,请使用您应该在RecurrencePeriod
上实施的方法,该方法将自己分裂为某个日期的两侧的两个RecurrencePeriod
,然后将更改保存到第二个时间段。如果他们仅修改该事件,则在他们覆盖的时间内创建一个OccurrenceOverride
,并将更改保存到覆盖的replacement_event。
当用户表示某个事件现在应该每隔两周在可预见的将来重复出现时,您应该创建一个新的RecurrencePeriod
,该事件的事件为base_event和nil end_date。它的复发应该是一个新的WeeklyRecurrence
,周期为between_recurrence = 2,它应该没有OccurrenceOverride
s。
只是一个意见了我的头顶,也许comenters会指出一个问题,我没有想到的目前:
我会做一个RecurringEvent
模型(或任何你想称之为)has_many :events
。
假设每个事件由员工创建(基于您的笔记),那么RecurringEvent
也将belong_to :employee
。然后,您可以建立一个员工有很多事件并且有许多重复事件的关系。
RecurringEvent模型可以有一个开始日期和一个模式,它最初可以使用这个模式来创建单个事件。然后,在任何属于重复系列赛的事件中,您可以修改或删除个人发生的事件,但是您也可以“重新生成系列”,删除系列中的所有事件(或系列中未来的所有事件)并根据一种新的模式,例如将会议从“每个星期二”移到“每个星期四”。
另外一件好事就是你可以创建一个反复发生的事件的一览表,这可能会让你对人们的主要义务有一个很好的认识。
就像我说过的那样,我的头顶就是这样,但这只是一个想法,我还没有建立这样的任何东西,所以我不知道是否有任何大的陷阱在我建议的方法中。
祝你好运,请张贴你最终做的事!
在我来说,我做了这样的事情:
# 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管理出现的计算和存储的结果出现表。我第一次尝试在没有发生模型的情况下工作,但无论规则引擎如何先进,您总会遇到异常情况,因此将事件存储在自己的模型中可以提供灵活性。
拥有一个发生模型使得在日历或日期搜索过滤器上显示事件变得容易很多,因为您只需查询发生次数,然后显示相关事件的数据,而不是收集给定日期中的所有事件然后必须过滤出时间表不匹配的事件。
而且可以标志一个事件发生的取消或修改(设置为false时生成的属性,以便编辑ice_cube时间表时,它不会被清理......或任何您的业务需求是)
中当然,如果您的事件无限期地重复发生,您可能希望限制您希望在将来生成多少事件,并使用自动化耙事任务清理旧事件,并在下一年左右生成事件。
到目前为止,这种模式对我来说工作得很好。
此外,看看recurring_select宝石,这是一个非常整洁的ice_cube形式输入。
我对Rails很新,你的解决方案听起来很有趣。要创建计划和相关事件,您是否在事件模型中使用条件回调?
在我的情况下,用户将能够创建事件,每周重复或不重复。所以我在考虑事件模型中的循环布尔型字段。所以我想你会第一回调创建时间表:
before_save :create_weekly_schedule, if: :recurring
和基本的第二个创建OCCURENCES:
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
这听起来逻辑与您的解决方案? Thx
我看到你回复[我的回答](http://*.com/a/10266450/578288)。当您回答特定答案时,您应该对该答案发表评论,否则作者将不会收到通知。另外,如果你的问题很长(像这样),不要把它放在原始问题的另一个答案上;在网站上创建一个与您答复的答案链接的新问题。 – 2014-10-02 00:50:37
至于我认为你的解决方案,我看到它的问题。你说'scheduleles.each' - 但是如果时间表只是“每周重复”,那么'each'循环将永远持续下去,因为时间表没有指定结束日期。这就是为什么我没有提前产生所有事件 - 其中有无数的事件。 – 2014-10-02 00:52:30
从没有持续发生,但不能通过id访问它的经验的任何问题? (性能,复杂性等) – ted 2013-09-04 15:59:17
@ted好的问题。我从来没有实现过,所以恐怕我不知道是否根据需要产生事件会导致任何问题。我想你可以根据需要为生成的事件设置一个缓存。缓存系统可能会使用这样一个事实,即生成的保存事件在概念上与“OccurrenceOverride”非常相似,尽管不完全相同。 – 2013-09-04 18:31:35