【问题标题】:Ruby: Experience with Gems for recurring calendar events? [closed]Ruby:在经常性日历事件中使用 Gems 的经验? [关闭]
【发布时间】:2011-07-15 03:35:51
【问题描述】:

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

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

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

  • Tickle - 好处是它可以解析英文。
  • Ice_Cube(+Schedule-Attributes) - 好处是它最受欢迎并且可以导出到 iCal

您能否推荐一颗宝石并描述使用它的积极和消极体验?

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

附:用 1,5K+ 添加 recurring_events 标签来安慰某人。谢谢

【问题讨论】:

  • @Greg,你能提供更多细节吗?您的印象和标准满足/未满足。谢谢
  • chronic 非常好,你找不到比 Ruby 更好的东西了。我使用它没有任何问题。没有直接使用 ri_cal 的经验,但我将在下一个项目中使用该 gem。

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


【解决方案1】:

我最终使用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

【讨论】:

    【解决方案2】:

    与 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 会随着您查询距当前日期的距离越远而减慢速度。

    【讨论】:

    • 我在这里打开了一个性能问题的问题(带有基准),以防有人跟进:github.com/seejohnrun/ice_cube/issues/33
    • 晚会有点晚了,但到此为止。您不应该检索所有内容然后在 Ruby 上调用它。我会在数据库本身中缓存这些事件(postgres 支持数组,所以这可能会派上用场)。因此,将其留给数据库来执行您可能需要的任何过滤。可能是比这更好的策略。
    • 那么有谁知道可以更好地处理这个问题的宝石,或者更好的方法来处理这个问题?即一个 gem,它可以更容易地处理大型计划,其中检查是否在某个日期发生等等是在数据库级别上计算出来的,而不是必须反序列化每一行并签入 ruby​​。
    • 我还没有看到任何宝石或其他技术可以根据 Ice Cube 中的公式快速生成“本周发生的所有事件”。通常,一些事件会被缓存,当人们仔细阅读日历时会生成更多事件。
    【解决方案3】:

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

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

    Rufus 文档有一些关于配对两种解决方案的说明。

    【讨论】:

      【解决方案4】:

      我建议看看 RubyToolbox 的 Recurring Events gems。它应该是最新的并且包括前面提到的 ice_cube。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-06
        • 2011-03-31
        • 2016-12-02
        • 2010-09-17
        • 1970-01-01
        相关资源
        最近更新 更多