Cronのスケジュール記法を解決する

Rails + BackgrounDRb 環境で、柔軟なスケジューリングをしたくて、Cron の記法を簡単に解決できないかなぁ、とBackgrounDRbのソースを読んでいたら、CronTrigger という便利なクラスがありました。

これを使えば Rails アプリから柔軟にスケジュールを制御できていい感じ。

# cron_test.rb
require 'vendor/plugins/backgroundrb/server/lib/cron_trigger'

cron = BackgrounDRb::CronTrigger.new("*/10 * 8-20 * * * *")
p cron.sec    # 秒
p cron.min   # 分
p cron.hour # 時


$ ruby cron_test.rb
[0, 10, 20, 30, 40, 50]
0..59
[8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

それぞれ秒、分、時間が配列で返るようです。
BackgrounDRb は cron と違って秒と年が追加されているので注意。

これを使って、

class CreateSchedules < ActiveRecord::Migration
  def self.up
    create_table :schedules do |t|
      t.column :cron, :string          # スケジュール
      t.column :task_id, :integer   # タスクを表すテーブルへの外部キーのイメージ
      t.timestamps
    end
  end

  def self.down
    drop_table :schedules
  end
end

のようにテーブルを作成して、カラムcronにスケジュールを入れるようにします。

class Schedule < ActiveRecord::Base
  def self.find_triggered(time = Time.now)
    find(:all).select do |sched|
      cron = BackgrounDRb::CronTrigger.new(sched.cron)
      cron.sec.include?(time.sec) and cron.min.include?(time.min) and cron.hour.include?(time.hour)
    end
  end  
end

のようにしておけば、Schedule.find_triggered で実行すべきタスクを取得できるようになります。
(注) 秒、分、時間以外は無視しています。

とても便利なのでCronTrigger.rb だけ切り出したい。