montrose 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 98eedcb18d91e3390bc4bf1e9962e2ddd4a596a3
4
- data.tar.gz: 3a43325e390bd795c81a5ee6246a413542a59509
3
+ metadata.gz: 72c7f27af8ab0e30ced7801cad42cf1243f9f79f
4
+ data.tar.gz: 228ad308e574dabefc4f5635e76dd878c8d105c9
5
5
  SHA512:
6
- metadata.gz: 6983022b0d6ba0aebc265c311362a5e24f6dba4a19d7334d198b0eb49b91161ddfc92276c1edb636d7d6e03bfb0039d41a8a72805932fa22e37917ac5a57676d
7
- data.tar.gz: 1264cd660fc3e6fff55485a7a273961147188935a0b22b162090ca63a9293f7a82d54459b04f7a69009aa797c9c73090ac44e7c4779c00207b3473415d52219f
6
+ metadata.gz: 94736a08ae987f52cd24adace44ce7414604d375a0d5281c823426cbc7f9d205fd25dccdbbacd46533cca4dc9bd424395374191ce26b75e4e8897e2ddc35ff25
7
+ data.tar.gz: ae7a298bc0ed9830656c85ef8cbb74faaf8eb7d22f1ecd854dde5e7ce8d1eefc5a223e27b3d2ecbe683a1113c807a29df205cfeb3ddc324832af0b251a6470b4
data/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ ### 0.2.0 - 2016-02-03
2
+
3
+ * enhancements
4
+ * extend `Montrose::Schedule` api for building and adding recurrences
5
+ * add more details to chainable docs
6
+ * merge default options at enumeration time for more consistent serialization
7
+
8
+ ### 0.1.1 - 2016-25-01
9
+
10
+ * bug fixes
11
+ * add missing `require "forwardable"`
12
+ * enhancements
13
+ * add better `#inspect` methods in `Recurrence` and `Options`
14
+ * use refinement to refactor Options internal arg merging
15
+ * support ruby 2.3.0 in travis builds
16
+
17
+ ### 0.1.0 - 2016-18-01
18
+
19
+ * initial release
data/README.md CHANGED
@@ -155,6 +155,7 @@ Montrose::Recurrence.new(every: :minute, until: "9:00 PM")
155
155
 
156
156
  # Daily
157
157
  Montrose.daily
158
+ Montrose.every(:day)
158
159
  Montrose::Recurrence.new(every: :day)
159
160
 
160
161
  Montrose.every(9.days)
@@ -218,18 +219,15 @@ Montrose.daily(except: [Date.today, "2017-01-31"])
218
219
  # Chaining
219
220
  Montrose.weekly.starting(3.weeks.from_now).on(:friday)
220
221
  Montrose.every(:day).at("4:05pm")
222
+ Montrose.yearly.between(Time.now..10.years.from_now)
221
223
 
222
224
  # Enumerating events
223
225
  r = Montrose.every(:month, mday: 31, until: "January 1, 2017")
224
226
  r.each { |time| puts time.to_s }
225
227
  r.take(10).to_a
226
228
 
227
- # Merging rules and enumerating
229
+ # Merging rules
228
230
  r.merge(starts: "2017-01-01").each { |time| puts time.to_s }
229
- r.merge(starts: "2017-01-01").each { |date| puts date.to_s }
230
- r.merge(until: "2017-01-10").each { |date| puts date.to_s }
231
- r.merge(through: "2017-01-10").each { |date| puts date.to_s }
232
- r.merge(starts: "2017-01-05", until: "2017-01-10").each {|date| puts date.to_s }
233
231
 
234
232
  # Using #events Enumerator
235
233
  r.events # => #<Enumerator: ...>
data/Rakefile CHANGED
@@ -4,10 +4,6 @@ require "rake/testtask"
4
4
  require "rubocop/rake_task"
5
5
  require "yard"
6
6
 
7
- YARD::Rake::YardocTask.new do |t|
8
- t.files = ["README.md", "lib/**/*.rb"]
9
- end
10
-
11
7
  Rake::TestTask.new(:spec) do |t|
12
8
  t.libs << "spec"
13
9
  t.libs << "lib"
@@ -19,3 +15,16 @@ task test: :spec
19
15
  RuboCop::RakeTask.new
20
16
 
21
17
  task default: [:spec, :rubocop]
18
+
19
+ namespace :doc do
20
+ desc "Generate docs and publish to gh-pages"
21
+ task :publish do
22
+ require "fileutils"
23
+ sh "yard doc"
24
+ sh "git checkout gh-pages"
25
+ sh "cp -R doc/* ."
26
+ sh "git commit -vam 'Update documentation'"
27
+ sh "git push origin gh-pages"
28
+ sh "git checkout -"
29
+ end
30
+ end
@@ -1,13 +1,19 @@
1
1
  require "montrose/options"
2
+ require "montrose/refinements/array_concat"
2
3
 
3
4
  module Montrose
4
5
  module Chainable
6
+ using Montrose::Refinements::ArrayConcat
7
+
5
8
  # Create a recurrence from the given frequency
6
- # @example
7
9
  #
10
+ # @param frequency [Symbol,String,Numeric] the recurrence frequency
11
+ # @param options [Hash] additional recurrence options
12
+ #
13
+ # @example
8
14
  # Montrose.every(:hour)
9
- # Montrose.every(:hour, interval: 2) #=> every 2 hours
10
- # Montrose.every(3.days, starts: 2.days.from_now) #=> every 3 days
15
+ # Montrose.every(:hour, interval: 2)
16
+ # Montrose.every(3.days, starts: 2.days.from_now)
11
17
  # Montrose.every(1.year, until: 10.days.from_now)
12
18
  #
13
19
  def every(frequency, options = {})
@@ -16,8 +22,9 @@ module Montrose
16
22
 
17
23
  # Create a minutely recurrence.
18
24
  #
19
- # @example
25
+ # @param options [Hash] additional recurrence options
20
26
  #
27
+ # @example
21
28
  # Montrose.minutely
22
29
  # Montrose.minutely(interval: 2) #=> every 2 minutes
23
30
  # Montrose.minutely(starts: 3.days.from_now)
@@ -31,8 +38,9 @@ module Montrose
31
38
 
32
39
  # Create a hourly recurrence.
33
40
  #
34
- # @example
41
+ # @param options [Hash] additional recurrence options
35
42
  #
43
+ # @example
36
44
  # Montrose.hourly
37
45
  # Montrose.hourly(interval: 2) #=> every 2 hours
38
46
  # Montrose.hourly(starts: 3.days.from_now)
@@ -46,8 +54,9 @@ module Montrose
46
54
 
47
55
  # Create a daily recurrence.
48
56
  #
49
- # @example
57
+ # @param options [Hash] additional recurrence options
50
58
  #
59
+ # @example
51
60
  # Montrose.daily
52
61
  # Montrose.daily(interval: 2) #=> every 2 days
53
62
  # Montrose.daily(starts: 3.days.from_now)
@@ -61,6 +70,8 @@ module Montrose
61
70
 
62
71
  # Create a weekly recurrence.
63
72
  #
73
+ # @param options [Hash] additional recurrence options
74
+ #
64
75
  # @example
65
76
  # Montrose.weekly(on: 5) #=> 0 = sunday, 1 = monday, ...
66
77
  # Montrose.weekly(on: :saturday)
@@ -74,14 +85,12 @@ module Montrose
74
85
 
75
86
  # Create a monthly recurrence.
76
87
  #
77
- # @example
78
- # Montrose.monthly(mday: [2, 15]) # 2nd and 15th of the month
79
- # Montrose.monthly(mday: -3) # third-to-last day of the month
80
- # Montrose.monthly(mday: 10..15) # 10th through the 15th day of the month
81
- #
82
- # The <tt>:on</tt> option can be one of the following:
88
+ # @param options [Hash] additional recurrence options
83
89
  #
84
- # * :sunday, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday
90
+ # @example
91
+ # Montrose.monthly(mday: [2, 15]) # 2nd and 15th of the month
92
+ # Montrose.monthly(mday: -3) # third-to-last day of the month
93
+ # Montrose.monthly(mday: 10..15) # 10th through the 15th day of the month
85
94
  #
86
95
  def monthly(options = {})
87
96
  branch options.merge(every: :month)
@@ -89,8 +98,9 @@ module Montrose
89
98
 
90
99
  # Create a yearly recurrence.
91
100
  #
92
- # @example
101
+ # @param options [Hash] additional recurrence options
93
102
  #
103
+ # @example
94
104
  # Montrose.yearly(on: [7, 14]) #=> every Jul 14
95
105
  # Montrose.yearly(on: [7, 14], interval: 2) #=> every 2 years on Jul 14
96
106
  # Montrose.yearly(on: [:jan, 14], interval: 2)
@@ -103,7 +113,10 @@ module Montrose
103
113
 
104
114
  # Create a recurrence starting at given timestamp.
105
115
  #
106
- # @param [Time, Date] starts_at
116
+ # @param starts_at [Time, Date] start time of recurrence
117
+ #
118
+ # @example
119
+ # Montrose.daily.starting(Date.tomorrow)
107
120
  #
108
121
  def starting(starts_at)
109
122
  merge(starts: starts_at)
@@ -111,7 +124,10 @@ module Montrose
111
124
 
112
125
  # Create a recurrence ending at given timestamp.
113
126
  #
114
- # @param [Time, Date] ends_at
127
+ # @param ends_at [Time, Date] end time of recurrence
128
+ #
129
+ # @example
130
+ # Montrose.daily.ending(1.year.from_now)
115
131
  #
116
132
  def ending(ends_at)
117
133
  merge(until: ends_at)
@@ -121,13 +137,20 @@ module Montrose
121
137
  #
122
138
  # @param [Range<Date>] date_range
123
139
  #
140
+ # @example
141
+ # Montrose.weekly.between(Date.today..Date.new(2016, 3, 15))
142
+ #
124
143
  def between(date_range)
125
144
  merge(between: date_range)
126
145
  end
127
146
 
128
147
  # Create a recurrence through :on option
129
148
  #
130
- # @param [Hash,Symbol] on { friday: 13 }
149
+ # @param day [Hash,Symbol] weekday or day of month as hash, e.g. { friday: 13 }
150
+ #
151
+ # @example
152
+ # Montrose.weekly.on(:friday)
153
+ # Montrose.monthly.on(friday: 13)
131
154
  #
132
155
  def on(day)
133
156
  merge(on: day)
@@ -135,7 +158,11 @@ module Montrose
135
158
 
136
159
  # Create a recurrence at given time
137
160
  #
138
- # @param [String,Time] at
161
+ # @param time [String,Time] represents time of day
162
+ #
163
+ # @example
164
+ # Montrose.daily.at("12pm")
165
+ # Montrose.daily.at("9:37am")
139
166
  #
140
167
  def at(time)
141
168
  merge(at: time)
@@ -143,69 +170,110 @@ module Montrose
143
170
 
144
171
  # Create a recurrence for given days of month
145
172
  #
146
- # @param [Fixnum] days (1, 2, -1, ...)
173
+ # @param days [Fixnum] days of month, e.g. 1, 2, -1, ...
147
174
  #
148
- def day_of_month(*days)
149
- merge(mday: days)
175
+ # @example
176
+ # Montrose.daily.day_of_month(1, -1)
177
+ # Montrose.daily.day_of_month([1, -1])
178
+ # Montrose.daily.day_of_month(2..8)
179
+ #
180
+ def day_of_month(days, *extras)
181
+ merge(mday: days.array_concat(extras))
150
182
  end
151
183
  alias mday day_of_month
152
184
 
153
185
  # Create a recurrence for given days of week
154
186
  #
155
- # @param [Symbol] weekdays (:sunday, :monday, ...)
187
+ # @param weekdays [Symbol] days of week, e.g. :sunday, :monday, ...
188
+ #
189
+ # @example
190
+ # Montrose.daily.day_of_week(:saturday)
191
+ # Montrose.daily.day_of_week(:monday, :tuesday)
192
+ # Montrose.daily.day_of_week(2..5)
156
193
  #
157
- def day_of_week(*weekdays)
158
- merge(day: weekdays)
194
+ def day_of_week(weekdays, *extras)
195
+ merge(day: weekdays.array_concat(extras))
159
196
  end
160
197
  alias day day_of_week
161
198
 
162
199
  # Create a recurrence for given days of year
163
200
  #
164
- # @param [Fixnum] days (1, 10, 100, ...)
201
+ # @param days [Fixnum, Range, Array<Integer>] days of year, e.g., 1, 10, 100, ...
165
202
  #
166
- def day_of_year(*days)
167
- merge(yday: days)
203
+ # @example
204
+ # Montrose.daily.day_of_year(1, 10, 100)
205
+ # Montrose.daily.day_of_year([1, 10, 100])
206
+ # Montrose.daily.day_of_year(20..50)
207
+ #
208
+ def day_of_year(days, *extras)
209
+ merge(yday: days.array_concat(extras))
168
210
  end
169
211
  alias yday day_of_year
170
212
 
171
213
  # Create a recurrence for given hours of day
172
214
  #
173
- # @param [Fixnum, Range] days (1, 10, 100, ...)
215
+ # @param hours [Fixnum, Range, Array<Integer>] hours of day, e.g. 1, 10, 100, ...
174
216
  #
175
- def hour_of_day(*hours)
176
- merge(hour: hours)
217
+ # @example
218
+ # Montrose.hourly.hour_of_day(9)
219
+ # Montrose.hourly.hour_of_day(15)
220
+ # Montrose.hourly.hour_of_day(6..10)
221
+ #
222
+ def hour_of_day(hours, *extras)
223
+ merge(hour: hours.array_concat(extras))
177
224
  end
178
225
  alias hour hour_of_day
179
226
 
180
227
  # Create a recurrence for given months of year
181
228
  #
182
- # @param [Fixnum, Symbol] months (:january, :april, ...)
229
+ # @param months [Fixnum, Symbol] months of year, e.g., :january, :april, ...
230
+ #
231
+ # @example
232
+ # Montrose.monthly.month_of_year(9)
233
+ # Montrose.monthly.month_of_year([2, 5])
234
+ # Montrose.monthly.month_of_year(2..5)
183
235
  #
184
- def month_of_year(*months)
185
- merge(month: months)
236
+ def month_of_year(months, *extras)
237
+ merge(month: months.array_concat(extras))
186
238
  end
187
239
  alias month month_of_year
188
240
 
241
+ # Create a recurrence for given weeks of year
242
+ #
243
+ # @param weeks [Fixnum] weeks of year, e.g., 1, 20, 50
244
+ #
245
+ # @example
246
+ # Montrose.weekly.week_of_year(9)
247
+ # Montrose.weekly.week_of_year([2, 5])
248
+ # Montrose.weekly.week_of_year(2..5)
249
+ #
250
+ def week_of_year(weeks, *extras)
251
+ merge(week: weeks.array_concat(extras))
252
+ end
253
+
189
254
  # Create a recurrence that ends after given number
190
255
  # of occurrences
191
256
  #
192
- # @param [Fixnum] total
257
+ # @param total [Fixnum] repeat count
258
+ #
259
+ # @example
260
+ # Montrose.daily.total(10)
193
261
  #
194
262
  def total(total)
195
263
  merge(total: total)
196
264
  end
197
265
 
198
- # Create a recurrence for given weeks of year
266
+ # Create a new recurrence combining options of self
267
+ # and other. The value of entries with duplicate
268
+ # keys will be those of other
199
269
  #
200
- # @param [Fixnum] weeks (1, 20, 50)
270
+ # @param opts [Hash,Montrose::Recurrence] other options or recurrence
201
271
  #
202
- def week_of_year(*weeks)
203
- merge(week: weeks)
204
- end
205
-
206
- # @private
207
- def merge(opts = {})
208
- branch default_options.merge(opts)
272
+ # @example
273
+ # Montrose.daily.total(10)
274
+ #
275
+ def merge(other = {})
276
+ branch default_options.merge(other)
209
277
  end
210
278
 
211
279
  # @private
@@ -3,7 +3,7 @@ require "montrose/errors"
3
3
  module Montrose
4
4
  class Clock
5
5
  def initialize(opts = {})
6
- @options = Montrose::Options.new(opts)
6
+ @options = Montrose::Options.merge(opts)
7
7
  @time = nil
8
8
  @every = @options.fetch(:every) { fail ConfigurationError, "Required option :every not provided" }
9
9
  @starts = @options.fetch(:starts)
@@ -44,13 +44,13 @@ module Montrose
44
44
  # when options contain given unit as a key or as a value of
45
45
  # the key :every in options
46
46
  #
47
- # @options = { every: :day, hour: 8.12 }
47
+ # options = { every: :day, hour: 8.12 }
48
48
  # unit_step(:minute)
49
49
  # => nil
50
50
  # unit_step(:hour)
51
51
  # => { hour: 1 }
52
52
  #
53
- # @options = { every: :hour, interval: 6 }
53
+ # options = { every: :hour, interval: 6 }
54
54
  # unit_step(:minute)
55
55
  # => nil
56
56
  # unit_step(:hour)
@@ -43,7 +43,7 @@ module Montrose
43
43
  end
44
44
 
45
45
  def initialize(opts = {})
46
- opts = Montrose::Options.new(opts)
46
+ opts = Montrose::Options.merge(opts)
47
47
  @time = nil
48
48
  @starts = opts.fetch(:starts)
49
49
  @interval = opts.fetch(:interval)
@@ -58,6 +58,18 @@ module Montrose
58
58
  @default_starts
59
59
  end
60
60
  end
61
+
62
+ def merge(opts = {})
63
+ new(default_options).merge(opts)
64
+ end
65
+
66
+ def default_options
67
+ {
68
+ starts: default_starts,
69
+ until: default_until,
70
+ interval: 1
71
+ }
72
+ end
61
73
  end
62
74
 
63
75
  def_option :every
@@ -78,9 +90,9 @@ module Montrose
78
90
  def initialize(opts = {})
79
91
  defaults = {
80
92
  every: self.class.default_every,
81
- starts: self.class.default_starts,
82
- until: self.class.default_until,
83
- interval: 1,
93
+ interval: nil,
94
+ starts: nil,
95
+ until: nil,
84
96
  day: nil,
85
97
  mday: nil,
86
98
  yday: nil,
@@ -272,7 +284,7 @@ module Montrose
272
284
 
273
285
  def assert_range_includes(range, item, absolute = false)
274
286
  test = absolute ? item.abs : item
275
- fail ConfigurationError, "Out of range" unless range.include?(test)
287
+ fail ConfigurationError, "Out of range: #{range.inspect} does not include #{test}" unless range.include?(test)
276
288
 
277
289
  item
278
290
  end
@@ -56,7 +56,7 @@ module Montrose
56
56
  private
57
57
 
58
58
  def event_enum
59
- opts = @default_options
59
+ opts = Options.merge(@default_options)
60
60
  stack = Stack.new(opts)
61
61
  clock = Clock.new(opts)
62
62
 
@@ -0,0 +1,11 @@
1
+ module Montrose
2
+ module Refinements
3
+ module ArrayConcat
4
+ refine Object do
5
+ def array_concat(other)
6
+ Array(self) + other
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -9,7 +9,7 @@ module Montrose
9
9
 
10
10
  # Initializes rule
11
11
  #
12
- # @param [Array<Fixnum>] hour - valid hours of days, e.g. [1, 2, 24]
12
+ # @param hours [Array<Fixnum>] valid hours of days, e.g. [1, 2, 24]
13
13
  #
14
14
  def initialize(hours)
15
15
  @hours = hours
@@ -2,6 +2,12 @@ module Montrose
2
2
  class Schedule
3
3
  attr_accessor :rules
4
4
 
5
+ def self.build
6
+ schedule = new
7
+ yield schedule if block_given?
8
+ schedule
9
+ end
10
+
5
11
  def initialize
6
12
  @rules = []
7
13
  end
@@ -21,8 +27,7 @@ module Montrose
21
27
  enums = @rules.map { |r| r.merge(opts).events }
22
28
  Enumerator.new do |y|
23
29
  loop do
24
- enums = active_enums(enums)
25
- enum = enums.min_by(&:peek) or break
30
+ enum = active_enums(enums).min_by(&:peek) or break
26
31
  y << enum.next
27
32
  end
28
33
  end
@@ -31,10 +36,11 @@ module Montrose
31
36
  private
32
37
 
33
38
  def active_enums(enums)
34
- enums.each_with_object([]) do |enum, actives|
39
+ enums.select do |e|
35
40
  begin
36
- actives << enum if enum.peek
41
+ e.peek
37
42
  rescue StopIteration
43
+ false
38
44
  end
39
45
  end
40
46
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Montrose
3
- VERSION = "0.1.1".freeze
3
+ VERSION = "0.2.0".freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: montrose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Kaffenberger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-25 00:00:00.000000000 Z
11
+ date: 2016-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -119,6 +119,7 @@ files:
119
119
  - ".gitignore"
120
120
  - ".rubocop.yml"
121
121
  - ".travis.yml"
122
+ - CHANGELOG.md
122
123
  - CODE_OF_CONDUCT.md
123
124
  - Gemfile
124
125
  - Guardfile
@@ -145,6 +146,7 @@ files:
145
146
  - lib/montrose/frequency/yearly.rb
146
147
  - lib/montrose/options.rb
147
148
  - lib/montrose/recurrence.rb
149
+ - lib/montrose/refinements/array_concat.rb
148
150
  - lib/montrose/rule.rb
149
151
  - lib/montrose/rule/after.rb
150
152
  - lib/montrose/rule/before.rb
@@ -184,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
186
  version: '0'
185
187
  requirements: []
186
188
  rubyforge_project:
187
- rubygems_version: 2.5.1
189
+ rubygems_version: 2.4.5.1
188
190
  signing_key:
189
191
  specification_version: 4
190
192
  summary: Recurring events in Ruby