Ruby:使用Gems体验重复发生的日历事件?

时间:2011-03-14 16:13:03

标签: ruby-on-rails ruby calendar gem recurring-events

我想为我的项目找到一个ruby gem来处理符合以下要求的reccuring事件:

  • 可以处理“星期二和星期三的每周”或“上周二的每月”等模式。
  • 可以计算下一次出现
  • 可以将模式序列化/反序列化为字符串以存储在数据库中
  • 序列化具有稳定的格式(即使在升级后也可以加载)
  • 至少使用以下模式组件:时间,星期几,月份日期,每月的第n天;
  • 可以每天,每周,每月或间隔n天,数周或数月重复
  • 可以用自然英语表示模式
  • 可以解析英语模式(可选)
  • 可以导出一些流行的格式,如iCal(可选)
  • 可以与其他宝石/系统集成以进行日历和任务管理(可选)
  • 支持Active Record - 参数解析,验证(可选)
  • 有足够的测试,很少有错误,超过1个用户:)
  • 具有合理的表现

我找到了两个相关的候选人:

  • 痒痒 - 好的是它可以解析英语。
  • Ice_Cube(+ Schedule-Attributes) - 最受欢迎的好处是可以导出到iCal

你能否建议一个宝石并用它描述积极和消极的经历?

也许你可以添加一些我没有提到的相关标准/要求。

P.S。 Pease某人用1,5K +添加recurring_events标记。感谢

4 个答案:

答案 0 :(得分:8)

由于以下原因,我最终使用Ice_Cube

  • Most popular
  • 可以计算下一次出现
  • 可以将模式序列化/反序列化为字符串以存储在数据库中
  • 序列化具有稳定的格式(即使在升级后也可以加载)
  • 至少使用以下模式组件:时间,星期几,月份日期,每月的第n天;
  • 可以每天,每周,每月或间隔n天,数周或数月重复
  • 可以解析英语模式(可选)
  • 可以导出一些流行的格式,如iCal(可选)

根据我的标准,这些不是由它填满的:

  • 可以用自然英语表示模式
  • 支持Active Record - 参数解析,验证(可选)

这个未经验证:

  • 具有合理的表现

从Rails中的用户输入创建Ice_Cube :: Schedule不是很方便,但可行:

class EntryForm < FormModel

  include IceCube
  class_eval &ValidatesTimelinessSupport[{:start_date => :datetime}]

  Units = [Day = 'day', Week = 'week']
  Intervals = %w[0 1 2 3 4 5 6 7 8 9]
  Week_Days = [:sunday, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday]

  Days_With_Letters = Week_Days.zip(%w[S M T W T F S])

  attr_accessible_accessors :interval, :unit, :start_date
  attr_accessible_accessors *Week_Days

  def_delegators :@model, :display_title, :schedule_yaml, :schedule_yaml=

  validates_date :start_date, :allow_blank => true
  validates_inclusion_of :unit, :in => Units
  validates_inclusion_of :interval, :in => Intervals
  validates_inclusion_of :complete, :in => %w[0 1], :allow_blank => true
  Week_Days.each { |day| validates_inclusion_of day, :in => %w[0 1], :allow_blank => true }

  before_edit {
    if not schedule_yaml.blank? and hash = YAML::load(schedule_yaml)
      schedule = Schedule.from_hash(hash)
    end

    if schedule and rule = schedule.rrules.first
      @start_date = schedule.start_date

      rule_hash = rule.to_hash
      @interval = rule_hash[:interval]

      case rule
      when DailyRule
        @unit = Day
      when WeeklyRule
        @unit = Week
        rule_hash[:validations][:day].try :each do |day_index|
          send "#{Week_Days[day_index]}=", 1
        end
      end

    else
      @start_date = Date.today
      @interval = 1
      @unit = Day
    end
  }

  before_save {
      sd = @start_date.blank? ?
          Date.today.to_all_day :
          @start_date.parse_date_in_timezone
      i = @interval.to_i
      schedule = Schedule.new(sd)


      rule = case @unit
        when Day
          Rule.daily i
        when Week
          Rule.weekly(i).day(
            *Week_Days.
            select { |day| send(day).to_i == 1 } )
      end

      schedule.add_recurrence_rule(rule)

      self.schedule_yaml = schedule.to_yaml
    end
  }
end

答案 1 :(得分:7)

和Ice_Cube一样可爱,它似乎不适合大规模调度应用程序,在这些应用程序中,您可能需要过滤100,000个事件以查看当天显示的内容。想想meetup.com

因为它全部被序列化为规则字符串,所以过滤主要列表的唯一方法似乎是这样的:

def self.entries_on(date)
    entries = TimetableEntry.all
    entries.reject{|te|!te.schedule.occurs_on?(date)}
end

效率不高。有人请认可我!!希望我错过了一个技巧?

也可以尝试上面的方法,使用日期为100年的日期......看起来好像ice_cube会使您从当前日期进一步查询速度变慢。

答案 2 :(得分:2)

我不知道有一个插件可以处理您的所有要求,但rufus-schedulerchronic的组合可以让您走得更远。

Rufus调度程序使用类似于cron的格式处理调度,该格式也适用于本地时区。 Chronic做自然语言解析。将它们组合在一起可以解决您的大部分需求。

Rufus文档中有关于配对这两种解决方案的一些注意事项。

答案 3 :(得分:2)

我建议看看RubyToolbox的Recurring Events宝石。它应该是最新的,包括之前提到的ice_cube。