Skip to content

Commit

Permalink
localized specs
Browse files Browse the repository at this point in the history
  • Loading branch information
tevio committed Dec 14, 2010
0 parents commit 7ebe42f
Show file tree
Hide file tree
Showing 13 changed files with 745 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pkg/*
*.gem
.bundle
9 changes: 9 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
source "http://rubygems.org"

# Specify your gem's dependencies in recurs.gemspec
gemspec

group :test do
gem 'rails', '3.0.1'
gem 'rspec'
end
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require 'bundler'
Bundler::GemHelper.install_tasks
245 changes: 245 additions & 0 deletions lib/recurs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
require 'util/module' unless defined? Rails
require 'recurs/consts'
require 'recurs/rules'
require 'ri_cal'
module Recurs
include RiCal
# Your code goes here...

module Parser

def self.included(base)
base.send :extend, ClassMethods
end

# class << self is NOT the same as including ( seen above ) which makes methods available to CLASSES that include the module
#, it ONLY makes the methods available to the MODULE itself
class << self
def rrule(repeats=nil, args={})
args[:rule] = :r
rule(repeats, args)
end

def exrule(repeats=nil, args={})
args[:rule] = :e
rule(repeats, args)
end

def rdate(dates=nil, args={})
args[:rule] = :r
date(dates, args)
end

def exdate(dates=nil, args={})
args[:rule] = :e
date(dates, args)
end

def date(dates=nil, args={})
args[:rule] == :r ? r = "RDATE" : r = "EXDATE"
if dates.is_a? Hash
f_dates = dates.flatten
if (f_dates[0] == :period) || (f_dates[0] == :range)
r += ";VALUE=PERIOD:"
i = 0
l = f_dates[1].length
e = 1
f_dates[1].each { |d|
r += RiCal::FastDateTime.from_date_time(d.to_datetime).ical_str
r += '/' if i == 0
r += ',' if (e < l) && (i != 0)
i += 1
e += 1
}
elsif f_dates[0] == :dates
r += ":"
l = f_dates[1].length
e = 1
f_dates[1].each {|d|
r += "#{RiCal::FastDateTime.from_date_time(d.to_datetime).ical_str}"
r += "," if (e < l)
e += 1
}
end
elsif dates.is_a?(Date) || dates.is_a?(DateTime)
r += ":#{RiCal::FastDateTime.from_date_time(dates.to_datetime).ical_str}"
end
r
end

protected
@@rule = nil

# The BYSECOND attr could be eg: 14 or multiple: 14, 45 between 0 and 59 ( i assume )
# The BYMINUTE attr could be eg: 14 or multiple: 14, 45 between 0 and 59 ( i assume )
# The BYSECOND attr could be eg: 14 or multiple: 14, 22 between 0 and 23 ( i assume )
# The BYDAY attribute allows you to specify exactly which days (SA, SU, MO, TU, WE, TH, FR)
# The BYMONTH is any month value between 1 .. 12
# the BYMONTHDAY is any value between 1 and 31
# WKST is the week starting on BYDAY eg SU,MO,TU,WE,TH

#args.each {|a| args[a[0]] = a[1].to_s.upcase if (a[1].is_a? String) || (a[1].is_a? Symbol)}


def rule(repeats, args = {})
args[:rule] == :r ? @@rule = "RRULE" : @@rule = "EXRULE"
@@rule += ":FREQ=#{repeats.to_s.upcase}"
interval(args)
args.each { |ar|
unless [:rule, :by_set_pos, :by_week_at, :count, :occurrences, :until, :ends_at, :repeats_every, :interval].include? ar[0]
@@rule += ";#{ar[0].to_s.gsub('_', '').upcase}=#{by_unit(ar[0], ar[1])}"
end
}
@@rule += ";BYSETPOS=#{args[:by_set_pos]}" if args[:by_set_pos]
@@rule += ";WKST=#{args[:by_week_st]}" if args[:by_week_st]
ending(args)
@@rule
end

def by_unit(measure, units)
ms = {:by_second => [60, get_num, BY_N_SECONDS],
:by_minute => [60, get_num, BY_N_MINUTES],
:by_hour => [23, get_num, BY_N_HOURS],
:by_day => [7, get_day_num, BY_DAYS],
:by_month_day => [31, get_day_num, BY_N_MONTH_DAYS],
:by_year_day => [366, get_day_num, BY_N_YEAR_DAYS],
:by_week => [52, get_num, BY_N_WEEKS],
:by_month => [12, get_month_num, BY_N_MONTHS]}

@measure = ms[measure]

r = ""
d = get_unit_nums(units)
comp = d.uniq.compact
c = comp.count
z = 0
comp.each { |i|
z += 1
r += @measure[2][i].to_s
r += "," unless z == c
}
r
end

def get_unit_nums(units)
r = []
# consts DAYS, BY_DAY
if units.is_a? Array
units.each { |d|
r << @measure[1].call(d)
}
else
r << @measure[1].call(units)
end
r
end

def get_num
->(num){
num.to_i.modulo(@measure[0]) unless num.is_a? Symbol;
}
end

def get_day_num
->(day){
if DAYS.include?(day.to_s.capitalize)
DAYS.find_index(day.to_s.capitalize)
elsif BY_DAYS.include?(day.to_s.upcase)
BY_DAYS.find_index(day.to_s.upcase)
else
day.to_i.modulo(7) unless day.is_a? Symbol
end;
}
end

def get_month_num
->(mon){
if MONTHS.include?(mon.to_s.capitalize)
MONTHS.find_index(mon.to_s.capitalize)
elsif BY_N_MONTHS.include?(mon.to_s.upcase)
BY_N_MONTHS.find_index(mon.to_s.upcase)
else
mon.to_i.modulo(12) unless mon.is_a? Symbol
end;
}
end

def interval(args)
if args[:repeats_every]
@@rule += ";INTERVAL=#{args[:repeats_every]}"
elsif args[:interval]
@@rule += ";INTERVAL=#{args[:interval]}"
end
end

def ending(args)
if args[:count]
@@rule += ";COUNT=#{args[:count]}"
elsif args[:occurrences]
@@rule += ";COUNT=#{args[:occurrences]}"
elsif args[:until]
@@rule += ";UNTIL=#{RiCal::FastDateTime.from_date_time(args[:until].to_datetime).ical_str}"
elsif args[:ends_at]
@@rule += ";UNTIL=#{RiCal::FastDateTime.from_date_time(args[:ends_at].to_datetime).ical_str}"
end
end

end

module ClassMethods
def acts_as_recurring
send :include, InstanceMethods
end
end

module InstanceMethods
def initialize
@rrules ||= []
@exrules ||= []
@rdates ||= []
@exdates ||= []
super
end

def recurs
r = @rrules
r.concat @exrules
r.concat @rdates
r.concat @exdates
r.join
end

def add_rrule(repeats, args = {})
rrule = Parser.rrule(repeats, args)
@rrules << rrule
rrule
end

def add_exrule(repeats, args = {})
exrule = Parser.exrule(repeats, args)
@exrules << exrule
exrule
end

def add_rdate(args = {})
rdate = Parser.rdate(args)
@rdates << rdate
rdate
end

def add_exdate(args = {})
exdate = Parser.exdate(args)
@exdates << exdate
exdate
end

protected
attr_accessor :rrules, :exrules, :rdates, :exdates
end


end


end
ActiveRecord::Base.send(:include, Recurs::Parser) if defined? Rails
40 changes: 40 additions & 0 deletions lib/recurs/consts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Recurs
#module Consts
# 0 1 2 3 4 5 6
DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
MONTHS = ['January', "February", 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December']
BY_N_SECONDS = (0..59).to_a
BY_N_MINUTES = (0..59).to_a
BY_N_HOURS = (0..23).to_a
BY_N_DAYS = (0..6).to_a
BY_N_MONTH_DAYS = (1..31).to_a
BY_N_YEAR_DAYS = (1..366).to_a
BY_DAYS = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']
BY_N_WEEKS = (1..54).to_a
BY_N_MONTHS = (1..12).to_a
BY_MONTHS = ['jan', 'feb', 'mar', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']

#SYM_DAYS = [:sunday, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday]
SYM_INTEGERS = [:zero, :one, :two, :three, :four, :five, :six, :seven, :eight, :nine, :ten]
SYM_TEENS = [:eleven, :twelve, :thirteen, :fourteen, :fifteen, :sixteen, :seventeen, :eighteen, :nineteen]
SYM_INTEGER_GROUP = SYM_INTEGERS+SYM_TEENS

# SYM_TENS[(34 - 34.modulo(10))/10]
SYM_TENS = [:ten, :twenty, :thirty, :fourty, :fifty, :sixty, :seventy, :eighty, :ninety, :hundred]

def get_integer_from_sym(sym)
SYM_INTEGER_GROUP(sym)
end

def build_num_sym(int)
if int > 19
r = int.modulo(10)
t = int - r
[SYM_TENS(t), SYM_INTEGERS[r]]
else
SYM_INTEGER_GROUP[int]
end
end
#end
end
92 changes: 92 additions & 0 deletions lib/recurs/rules.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
module Recurs
module Rules
mattr_accessor :repeat_procs, :schema
@@repeat_procs = {

=begin
'Daily' => ->(args = {}){
args[:repeats] = 'DAILY'
rrule(args);
}, # 0
=end

#=begin
'Daily' => ->(set=false, args = {}){
unless set
@recurrence_template = ['standard','Days']
else
Parser.rrule(:daily, args)
end;
}, # 0
#=end

'Every Weekday ( Mon - Fri )' => ->(set=false, args = {}){
unless set
@recurrence_template = 'set_points'
else
args[:by_day] = [1,2,3,4,5]
Parser.rrule(:weekly, args)
#
# .
end;
}, # 1

'Every Mon, Wed, Fri' => ->(set=false, args = {}){
unless set
@recurrence_template = 'set_points'
else
args[:by_day] = [1,3,5]
Parser.rrule(:weekly, args)
end;
}, # 2

'Every Tues, Thurs' => ->(set=false, args = {}){
unless set
@recurrence_template = 'set_points'
else
args[:by_day] = [2,4]
Parser.rrule(:weekly, args)
end;
}, # 3

'Every Weekend' => ->(set=false, args = {}){
unless set
@recurrence_template = 'set_points'
else
args[:by_day] = [0,6]
Parser.rrule(:weekly, args)
end;
}, # 4

'Weekly' => ->(set=false, args = {}){
unless set
@recurrence_template = ['weekly', 'Weeks']
else
Parser.rrule(:weekly, args)
end;
}, # 5

'Monthly' => ->(set=false, args = {}){
unless set
@recurrence_template = ['monthly', 'Months']
else
Parser.rrule(:monthly, args)
end;
}, # 6

'Yearly' => ->(set=false, args = {}){
unless set
@recurrence_template = ['standard', 'Years']
else
Parser.rrule(:yearly, args)
end;
} # 7

}
class << self
def schemes
@@schemas = @@repeat_procs.keys if @@repeat_procs.is_a? Hash
end
end
end
end
Loading

0 comments on commit 7ebe42f

Please sign in to comment.