ice_cube 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)