ice_cube 0.11.0 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ice_cube.rb +0 -11
  3. data/lib/ice_cube/builders/string_builder.rb +15 -23
  4. data/lib/ice_cube/deprecated.rb +26 -24
  5. data/lib/ice_cube/enumerator.rb +1 -3
  6. data/lib/ice_cube/hash_input.rb +71 -0
  7. data/lib/ice_cube/rule.rb +4 -6
  8. data/lib/ice_cube/rules/daily_rule.rb +1 -1
  9. data/lib/ice_cube/rules/hourly_rule.rb +1 -1
  10. data/lib/ice_cube/rules/minutely_rule.rb +1 -1
  11. data/lib/ice_cube/rules/monthly_rule.rb +1 -1
  12. data/lib/ice_cube/rules/secondly_rule.rb +1 -1
  13. data/lib/ice_cube/rules/yearly_rule.rb +1 -1
  14. data/lib/ice_cube/schedule.rb +4 -4
  15. data/lib/ice_cube/string_helpers.rb +10 -0
  16. data/lib/ice_cube/time_util.rb +14 -5
  17. data/lib/ice_cube/validations/count.rb +4 -6
  18. data/lib/ice_cube/validations/daily_interval.rb +13 -18
  19. data/lib/ice_cube/validations/day.rb +4 -4
  20. data/lib/ice_cube/validations/day_of_month.rb +8 -10
  21. data/lib/ice_cube/validations/day_of_week.rb +24 -26
  22. data/lib/ice_cube/validations/day_of_year.rb +11 -12
  23. data/lib/ice_cube/validations/hour_of_day.rb +9 -11
  24. data/lib/ice_cube/validations/hourly_interval.rb +18 -21
  25. data/lib/ice_cube/validations/lock.rb +35 -14
  26. data/lib/ice_cube/validations/minute_of_hour.rb +9 -11
  27. data/lib/ice_cube/validations/minutely_interval.rb +16 -19
  28. data/lib/ice_cube/validations/month_of_year.rb +4 -4
  29. data/lib/ice_cube/validations/monthly_interval.rb +15 -17
  30. data/lib/ice_cube/validations/schedule_lock.rb +12 -11
  31. data/lib/ice_cube/validations/second_of_minute.rb +5 -5
  32. data/lib/ice_cube/validations/secondly_interval.rb +13 -16
  33. data/lib/ice_cube/validations/until.rb +12 -12
  34. data/lib/ice_cube/validations/weekly_interval.rb +20 -23
  35. data/lib/ice_cube/validations/yearly_interval.rb +10 -11
  36. data/lib/ice_cube/version.rb +1 -1
  37. metadata +20 -33
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0cf51eea4a5e3f9a8c15eedc224978494d2a79df
4
+ data.tar.gz: 8daed67d6ab9f6e610ea40c08e7e032a96552e47
5
+ SHA512:
6
+ metadata.gz: 7acfe2a1546d074b0b43a9250ce4e937f339f084fd3abf9a04b840cc529849140d224b4d2bdd134254ecf1088c19e6845fce195b9440eea2fddbb31baa25ca2b
7
+ data.tar.gz: d722e7ef0d0ee4fb2bfaaf5e28b330df6898ad49f183f2cb0ab43e6115bcf91be64cd07755df568318dd83deffe94439b83ec8ba0c60f2b06711d39a3c174534
data/lib/ice_cube.rb CHANGED
@@ -1,13 +1,6 @@
1
1
  require 'date'
2
2
  require 'ice_cube/deprecated'
3
3
 
4
- # Use psych if we can
5
- begin
6
- require 'psych'
7
- rescue LoadError
8
- require 'yaml'
9
- end
10
-
11
4
  module IceCube
12
5
 
13
6
  autoload :VERSION, 'ice_cube/version'
@@ -71,10 +64,6 @@ module IceCube
71
64
  ONE_DAY = ONE_HOUR * 24
72
65
  ONE_WEEK = ONE_DAY * 7
73
66
 
74
- def self.use_psych?
75
- @use_psych ||= defined?(Psych) && defined?(Psych::VERSION)
76
- end
77
-
78
67
  # Defines the format used by IceCube when printing out Schedule#to_s.
79
68
  # Defaults to '%B %e, %Y'
80
69
  def self.to_s_time_format
@@ -13,32 +13,26 @@ module IceCube
13
13
  end
14
14
 
15
15
  def to_s
16
- str = @base || ''
17
- res = @types.map do |type, segments|
16
+ @types.each_with_object(@base || '') do |(type, segments), str|
18
17
  if f = self.class.formatter(type)
19
- str << ' ' + f.call(segments)
18
+ str << ' ' << f.call(segments)
20
19
  else
21
20
  next if segments.empty?
22
- str << ' ' + self.class.sentence(segments)
21
+ str << ' ' << self.class.sentence(segments)
23
22
  end
24
23
  end
25
- str
26
24
  end
27
25
 
28
- class << self
29
-
30
- def formatter(type)
31
- @formatters[type]
32
- end
33
-
34
- def register_formatter(type, &formatter)
35
- @formatters ||= {}
36
- @formatters[type] = formatter
37
- end
26
+ def self.formatter(type)
27
+ @formatters[type]
28
+ end
38
29
 
30
+ def self.register_formatter(type, &formatter)
31
+ @formatters ||= {}
32
+ @formatters[type] = formatter
39
33
  end
40
34
 
41
- class << self
35
+ module Helpers
42
36
 
43
37
  NUMBER_SUFFIX = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th']
44
38
  SPECIAL_SUFFIX = { 11 => 'th', 12 => 'th', 13 => 'th', 14 => 'th' }
@@ -54,21 +48,19 @@ module IceCube
54
48
  end
55
49
 
56
50
  def nice_number(number)
57
- if number == -1
58
- 'last'
59
- elsif number < -1
60
- suffix = SPECIAL_SUFFIX.include?(number) ?
61
- SPECIAL_SUFFIX[number] : NUMBER_SUFFIX[number.abs % 10]
51
+ return 'last' if number == -1
52
+ suffix = SPECIAL_SUFFIX[number] || NUMBER_SUFFIX[number.abs % 10]
53
+ if number < -1
62
54
  number.abs.to_s << suffix << ' to last'
63
55
  else
64
- suffix = SPECIAL_SUFFIX.include?(number) ?
65
- SPECIAL_SUFFIX[number] : NUMBER_SUFFIX[number.abs % 10]
66
56
  number.to_s << suffix
67
57
  end
68
58
  end
69
59
 
70
60
  end
71
61
 
62
+ extend Helpers
63
+
72
64
  end
73
65
 
74
66
  end
@@ -1,28 +1,30 @@
1
- module Deprecated
1
+ module IceCube
2
+ module Deprecated
2
3
 
3
- # Define a deprecated alias for a method
4
- # @param [Symbol] name - name of method to define
5
- # @param [Symbol] replacement - name of method to replace (alias)
6
- def deprecated_alias(name, replacement)
7
- # Create a wrapped version
8
- define_method(name) do |*args, &block|
9
- warn "IceCube: ##{name} deprecated (please use ##{replacement})"
10
- send replacement, *args, &block
11
- end
12
- end
4
+ # Define a deprecated alias for a method
5
+ # @param [Symbol] name - name of method to define
6
+ # @param [Symbol] replacement - name of method to replace (alias)
7
+ def deprecated_alias(name, replacement)
8
+ # Create a wrapped version
9
+ define_method(name) do |*args, &block|
10
+ warn "IceCube: ##{name} deprecated (please use ##{replacement})"
11
+ send replacement, *args, &block
12
+ end
13
+ end
13
14
 
14
- # Deprecate a defined method
15
- # @param [Symbol] name - name of deprecated method
16
- # @param [Symbol] replacement - name of the desired replacement
17
- def deprecated(name, replacement)
18
- # Replace old method
19
- old_name = :"#{name}_without_deprecation"
20
- alias_method old_name, name
21
- # And replace it with a wrapped version
22
- define_method(name) do |*args, &block|
23
- warn "IceCube: ##{name} deprecated (please use ##{replacement})"
24
- send old_name, *args, &block
25
- end
26
- end
15
+ # Deprecate a defined method
16
+ # @param [Symbol] name - name of deprecated method
17
+ # @param [Symbol] replacement - name of the desired replacement
18
+ def deprecated(name, replacement)
19
+ # Replace old method
20
+ old_name = :"#{name}_without_deprecation"
21
+ alias_method old_name, name
22
+ # And replace it with a wrapped version
23
+ define_method(name) do |*args, &block|
24
+ warn "IceCube: ##{name} deprecated (please use ##{replacement})"
25
+ send old_name, *args, &block
26
+ end
27
+ end
27
28
 
29
+ end
28
30
  end
@@ -19,11 +19,9 @@ module IceCube
19
19
  def find_next
20
20
  loop do
21
21
  min_time = recurrence_rules.reduce(nil) do |min_time, rule|
22
- begin
22
+ catch :limit do
23
23
  new_time = rule.next_time(time, schedule, min_time || @to_time)
24
24
  [min_time, new_time].compact.min
25
- rescue CountExceeded, UntilExceeded
26
- min_time
27
25
  end
28
26
  end
29
27
  break nil unless min_time
@@ -0,0 +1,71 @@
1
+ module IceCube
2
+ class HashInput
3
+
4
+ class Mash
5
+ def initialize(hash)
6
+ @hash = hash
7
+ end
8
+
9
+ # Fetch values indifferently by symbol or string key without symbolizing
10
+ # arbitrary string input
11
+ #
12
+ def [](key)
13
+ @hash.fetch(key) do |key|
14
+ str_key = key.to_s
15
+ @hash.each_pair.detect do |sym_key, value|
16
+ return value if sym_key.to_s == str_key
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def initialize(hash)
23
+ @input = Mash.new(hash)
24
+ end
25
+
26
+ def [](key)
27
+ @input[key]
28
+ end
29
+
30
+ def to_rule
31
+ return nil unless rule_class
32
+ rule = rule_class.new(interval, week_start)
33
+ rule.until(limit_time) if limit_time
34
+ rule.count(limit_count) if limit_count
35
+ validations.each do |validation, args|
36
+ rule.send(validation, *args)
37
+ end
38
+ end
39
+
40
+ def rule_class
41
+ return @rule_class if @rule_class
42
+ match = @input[:rule_type].match(/::(\w+Rule)$/)
43
+ @rule_class = IceCube.const_get(match[1]) if match
44
+ end
45
+
46
+ def interval
47
+ @input[:interval] || 1
48
+ end
49
+
50
+ def week_start
51
+ @input[:week_start] || :sunday
52
+ end
53
+
54
+ def limit_time
55
+ @limit_time ||= TimeUtil.deserialize_time(@input[:until])
56
+ end
57
+
58
+ def limit_count
59
+ @input[:count]
60
+ end
61
+
62
+ def validations
63
+ input_validations = Mash.new(@input[:validations] || {})
64
+ ValidatedRule::VALIDATION_ORDER.each_with_object({}) do |key, output_validations|
65
+ args = input_validations[key]
66
+ output_validations[key] = Array(args) if args
67
+ end
68
+ end
69
+
70
+ end
71
+ end
data/lib/ice_cube/rule.rb CHANGED
@@ -23,24 +23,22 @@ module IceCube
23
23
  h.nil? ? super : h.hash
24
24
  end
25
25
 
26
- # Expected to be overridden by subclasses
27
26
  def to_ical
28
- nil
27
+ raise MethodNotImplemented, "Expected to be overrridden by subclasses"
29
28
  end
30
29
 
31
30
  # Yaml implementation
32
31
  def to_yaml(*args)
33
- IceCube::use_psych? ? Psych::dump(to_hash) : YAML::dump(to_hash, *args)
32
+ YAML::dump(to_hash, *args)
34
33
  end
35
34
 
36
35
  # From yaml
37
36
  def self.from_yaml(yaml)
38
- from_hash IceCube::use_psych? ? Psych::load(yaml) : YAML::load(yaml)
37
+ from_hash YAML::load(yaml)
39
38
  end
40
39
 
41
- # Expected to be overridden by subclasses
42
40
  def to_hash
43
- nil
41
+ raise MethodNotImplemented, "Expected to be overridden by subclasses"
44
42
  end
45
43
 
46
44
  # Convert from a hash and create a rule
@@ -4,7 +4,7 @@ module IceCube
4
4
 
5
5
  include Validations::DailyInterval
6
6
 
7
- def initialize(interval = 1)
7
+ def initialize(interval = 1, week_start = :sunday)
8
8
  super
9
9
  interval(interval)
10
10
  schedule_lock(:hour, :min, :sec)
@@ -4,7 +4,7 @@ module IceCube
4
4
 
5
5
  include Validations::HourlyInterval
6
6
 
7
- def initialize(interval = 1)
7
+ def initialize(interval = 1, week_start = :sunday)
8
8
  super
9
9
  interval(interval)
10
10
  schedule_lock(:min, :sec)
@@ -4,7 +4,7 @@ module IceCube
4
4
 
5
5
  include Validations::MinutelyInterval
6
6
 
7
- def initialize(interval = 1)
7
+ def initialize(interval = 1, week_start = :sunday)
8
8
  super
9
9
  interval(interval)
10
10
  schedule_lock(:sec)
@@ -4,7 +4,7 @@ module IceCube
4
4
 
5
5
  include Validations::MonthlyInterval
6
6
 
7
- def initialize(interval = 1)
7
+ def initialize(interval = 1, week_start = :sunday)
8
8
  super
9
9
  interval(interval)
10
10
  schedule_lock(:day, :hour, :min, :sec)
@@ -4,7 +4,7 @@ module IceCube
4
4
 
5
5
  include Validations::SecondlyInterval
6
6
 
7
- def initialize(interval = 1)
7
+ def initialize(interval = 1, week_start = :sunday)
8
8
  super
9
9
  interval(interval)
10
10
  reset
@@ -4,7 +4,7 @@ module IceCube
4
4
 
5
5
  include Validations::YearlyInterval
6
6
 
7
- def initialize(interval = 1)
7
+ def initialize(interval = 1, week_start = :sunday)
8
8
  super
9
9
  interval(interval)
10
10
  schedule_lock(:month, :day, :hour, :min, :sec)
@@ -4,7 +4,7 @@ module IceCube
4
4
 
5
5
  class Schedule
6
6
 
7
- extend ::Deprecated
7
+ extend Deprecated
8
8
 
9
9
  # Get the start time
10
10
  attr_reader :start_time
@@ -237,7 +237,7 @@ module IceCube
237
237
  def conflicts_with?(other_schedule, closing_time = nil)
238
238
  closing_time = TimeUtil.ensure_time closing_time
239
239
  unless terminating? || other_schedule.terminating? || closing_time
240
- raise ArgumentError.new 'At least one schedule must be terminating to use #conflicts_with?'
240
+ raise ArgumentError, "One or both schedules must be terminating to use #conflicts_with?"
241
241
  end
242
242
  # Pick the terminating schedule, and other schedule
243
243
  # No need to reverse if terminating? or there is a closing time
@@ -313,12 +313,12 @@ module IceCube
313
313
 
314
314
  # Convert the schedule to yaml
315
315
  def to_yaml(*args)
316
- IceCube::use_psych? ? Psych::dump(to_hash, *args) : YAML::dump(to_hash, *args)
316
+ YAML::dump(to_hash, *args)
317
317
  end
318
318
 
319
319
  # Load the schedule from yaml
320
320
  def self.from_yaml(yaml, options = {})
321
- hash = IceCube::use_psych? ? Psych::load(yaml) : YAML::load(yaml)
321
+ hash = YAML::load(yaml)
322
322
  if match = yaml.match(/start_date: .+((?:-|\+)\d{2}:\d{2})$/)
323
323
  TimeUtil.restore_deserialized_offset(hash[:start_date], match[1])
324
324
  end
@@ -0,0 +1,10 @@
1
+ module IceCube
2
+ module StringHelpers
3
+
4
+ module_function
5
+
6
+ def nice_number(number)
7
+ end
8
+
9
+ end
10
+ end
@@ -3,7 +3,7 @@ require 'date'
3
3
  module IceCube
4
4
  module TimeUtil
5
5
 
6
- extend ::Deprecated
6
+ extend Deprecated
7
7
 
8
8
  DAYS = {
9
9
  :sunday => 0, :monday => 1, :tuesday => 2, :wednesday => 3,
@@ -82,7 +82,7 @@ module IceCube
82
82
  # keep it. If it was serialized with a different offset than local TZ it
83
83
  # will lose the zone and not support DST.
84
84
  def self.restore_deserialized_offset(time, orig_offset_str)
85
- return time if time.respond_to?(:time_zone) or
85
+ return time if time.respond_to?(:time_zone) ||
86
86
  time.getlocal(orig_offset_str).utc_offset == time.utc_offset
87
87
  warn 'IceCube: parsed Time from nonlocal TZ. Use ActiveSupport to fix DST'
88
88
  time.localtime(orig_offset_str)
@@ -113,21 +113,30 @@ module IceCube
113
113
  # Convert a symbol to a numeric month
114
114
  def self.sym_to_month(sym)
115
115
  return wday = sym if (1..12).include? sym
116
- MONTHS.fetch(sym) { |k| raise KeyError, "No such month: #{k}" }
116
+ MONTHS.fetch(sym) do |k|
117
+ raise ArgumentError, "Expecting Fixnum or Symbol value for month. " \
118
+ "No such month: #{k.inspect}"
119
+ end
117
120
  end
118
121
  deprecated_alias :symbol_to_month, :sym_to_month
119
122
 
120
123
  # Convert a symbol to a wday number
121
124
  def self.sym_to_wday(sym)
122
125
  return sym if (0..6).include? sym
123
- DAYS.fetch(sym) { |k| raise KeyError, "No such weekday: #{k}" }
126
+ DAYS.fetch(sym) do |k|
127
+ raise ArgumentError, "Expecting Fixnum or Symbol value for weekday. " \
128
+ "No such weekday: #{k.inspect}"
129
+ end
124
130
  end
125
131
  deprecated_alias :symbol_to_day, :sym_to_wday
126
132
 
127
133
  # Convert wday number to day symbol
128
134
  def self.wday_to_sym(wday)
129
135
  return sym = wday if DAYS.keys.include? wday
130
- DAYS.invert.fetch(wday) { |i| raise KeyError, "No such wday number: #{i}" }
136
+ DAYS.invert.fetch(wday) do |i|
137
+ raise ArgumentError, "Expecting Fixnum value for weekday. " \
138
+ "No such wday number: #{i.inspect}"
139
+ end
131
140
  end
132
141
 
133
142
  # Convert weekday from base sunday to the schedule's week start.
@@ -2,7 +2,7 @@ module IceCube
2
2
 
3
3
  module Validations::Count
4
4
 
5
- # accessor
5
+ # Value reader for limit
6
6
  def occurrence_count
7
7
  @count
8
8
  end
@@ -12,7 +12,7 @@ module IceCube
12
12
  raise ArgumentError, "Expecting Fixnum or nil value for count, got #{max.inspect}"
13
13
  end
14
14
  @count = max
15
- replace_validations_for(:count, [Validation.new(max, self)])
15
+ replace_validations_for(:count, max && [Validation.new(max, self)])
16
16
  self
17
17
  end
18
18
 
@@ -26,13 +26,11 @@ module IceCube
26
26
  end
27
27
 
28
28
  def type
29
- :dealbreaker
29
+ :limit
30
30
  end
31
31
 
32
32
  def validate(time, schedule)
33
- if rule.uses && rule.uses >= count
34
- raise CountExceeded
35
- end
33
+ raise CountExceeded if rule.uses && rule.uses >= count
36
34
  end
37
35
 
38
36
  def build_s(builder)