by_star 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/mysql.yml +92 -0
  3. data/.github/workflows/postgresql.yml +99 -0
  4. data/.gitignore +1 -0
  5. data/.travis.yml +67 -36
  6. data/CHANGELOG.md +15 -0
  7. data/README.md +172 -133
  8. data/UPGRADING +1 -3
  9. data/by_star.gemspec +2 -2
  10. data/lib/by_star/base.rb +16 -15
  11. data/lib/by_star/between.rb +81 -52
  12. data/lib/by_star/directional.rb +2 -4
  13. data/lib/by_star/kernel/date.rb +0 -9
  14. data/lib/by_star/kernel/in_time_zone.rb +20 -0
  15. data/lib/by_star/normalization.rb +52 -23
  16. data/lib/by_star/orm/active_record/by_star.rb +20 -6
  17. data/lib/by_star/orm/mongoid/by_star.rb +20 -6
  18. data/lib/by_star/version.rb +1 -1
  19. data/lib/by_star.rb +1 -0
  20. data/spec/database.yml +1 -1
  21. data/spec/fixtures/active_record/models.rb +2 -2
  22. data/spec/fixtures/mongoid/models.rb +1 -1
  23. data/spec/fixtures/shared/seeds.rb +10 -0
  24. data/spec/gemfiles/Gemfile.rails +5 -0
  25. data/spec/gemfiles/Gemfile.rails32 +7 -0
  26. data/spec/gemfiles/Gemfile.rails40 +1 -1
  27. data/spec/gemfiles/Gemfile.rails41 +1 -1
  28. data/spec/gemfiles/Gemfile.rails42 +2 -2
  29. data/spec/gemfiles/Gemfile.rails50 +1 -4
  30. data/spec/gemfiles/Gemfile.rails51 +1 -4
  31. data/spec/gemfiles/Gemfile.rails52 +7 -0
  32. data/spec/gemfiles/Gemfile.rails60 +7 -0
  33. data/spec/gemfiles/Gemfile.rails61 +7 -0
  34. data/spec/integration/active_record/active_record_spec.rb +6 -3
  35. data/spec/integration/mongoid/mongoid_spec.rb +3 -1
  36. data/spec/integration/shared/at_time.rb +53 -0
  37. data/spec/integration/shared/between_dates.rb +99 -0
  38. data/spec/integration/shared/between_times.rb +27 -10
  39. data/spec/integration/shared/by_day.rb +24 -0
  40. data/spec/integration/shared/by_direction.rb +11 -57
  41. data/spec/integration/shared/index_scope_parameter.rb +111 -0
  42. data/spec/spec_helper.rb +4 -0
  43. data/spec/unit/kernel_date_spec.rb +6 -6
  44. data/spec/unit/normalization_spec.rb +128 -49
  45. metadata +33 -21
  46. data/spec/gemfiles/Gemfile.master +0 -6
  47. data/spec/integration/shared/scope_parameter.rb +0 -73
data/README.md CHANGED
@@ -8,12 +8,12 @@ ByStar (by_*) allows you easily and reliably query ActiveRecord and Mongoid obje
8
8
  ### Examples
9
9
 
10
10
  ```ruby
11
- Post.by_year(2013) # all posts in 2013
12
- Post.before(Date.today) # all posts for before today
13
- Post.yesterday # all posts for yesterday
14
- Post.between_times(Time.zone.now - 3.hours, # all posts in last 3 hours
15
- Time.zone.now)
16
- @post.next # next post after a given post
11
+ Post.by_year(2013) # all posts in 2013
12
+ Post.before(Date.today) # all posts for before today
13
+ Post.yesterday # all posts for yesterday
14
+ Post.between_times(Time.zone.now - 3.hours, # all posts in last 3 hours
15
+ Time.zone.now)
16
+ @post.next # next post after a given post
17
17
  ```
18
18
 
19
19
  ## Installation
@@ -21,7 +21,7 @@ ByStar (by_*) allows you easily and reliably query ActiveRecord and Mongoid obje
21
21
  Install this gem by adding this to your Gemfile:
22
22
 
23
23
  ```ruby
24
- gem 'by_star', git: "git://github.com/radar/by_star"
24
+ gem 'by_star', git: 'https://github.com/radar/by_star'
25
25
  ```
26
26
 
27
27
  Then run `bundle install`
@@ -44,30 +44,36 @@ class MyModel
44
44
  ByStar adds the following finder scopes (class methods) to your model to query time ranges.
45
45
  These accept a `Date`, `Time`, or `DateTime` object as an argument, which defaults to `Time.zone.now` if not specified:
46
46
 
47
- * `between_times(start_time, end_time)` - Finds all records occurring between the two given times.
48
- * `before(end_time)` - Finds all records occurring before the given time
49
- * `after(start_time)` - Finds all records occurring after the given time
47
+ | Scope | Meaning |
48
+ | --- | --- |
49
+ | `between_times(start_time, end_time)` | Finds all records occurring between two given times. |
50
+ | `between_dates(start_date, end_date)` | Finds all records occurring between two given dates, from beginning of start_date until end of end_date. |
51
+ | `before(end_time)` | Finds all records occurring before the given time. |
52
+ | `after(start_time)` | Finds all records occurring after the given time. |
53
+ | `at_time(time)` | Finds all records occurring exactly at the given time, or which overlap the time in the case of "timespan"-type object (see below) |
50
54
 
51
- `between_times` supports alternate argument forms:
52
- * `between_times(Range)`
53
- * `between_times(Array)`
54
- * `between_times(start_time, nil)` - same as `after(start_time)`
55
- * `between_times(nil, end_time)` - same as `before(end_time)`
55
+ `between_times` and `between_dates` supports alternate argument forms:
56
+ * `between_times(Range)`
57
+ * `between_times(Array)`
58
+ * `between_times(start_time, nil)` - same as `after(start_time)`
59
+ * `between_times(nil, end_time)` - same as `before(end_time)`
56
60
 
57
61
  ### Time Range Scopes
58
62
 
59
63
  ByStar adds additional shortcut scopes based on commonly used time ranges.
60
64
  See sections below for detailed argument usage of each:
61
65
 
62
- * `by_day`
63
- * `by_week` Allows zero-based week value from 0 to 52
64
- * `by_cweek` Allows one-based week value from 1 to 53
65
- * `by_weekend` Saturday and Sunday only of the given week
66
- * `by_fortnight` A two-week period, with the first fortnight of the year beginning on 1st January
67
- * `by_month`
68
- * `by_calendar_month` Month as it appears on a calendar; days form previous/following months which are part of the first/last weeks of the given month
69
- * `by_quarter` 3-month intervals of the year
70
- * `by_year`
66
+ | Scope | Meaning |
67
+ | --- | --- |
68
+ | `by_day` | Query by a given date. |
69
+ | `by_week` | Allows zero-based week value from 0 to 52. |
70
+ | `by_cweek` | Allows one-based week value from 1 to 53. |
71
+ | `by_weekend` | Saturday and Sunday only of the given week. |
72
+ | `by_fortnight` | A two-week period, with the first fortnight of the year beginning on 1st January. |
73
+ | `by_month` | Query by month. Allows integer arg, e.g. `11` for November. |
74
+ | `by_calendar_month` | Month as it appears on a calendar; days form previous/following months which are part of the first/last weeks of the given month. |
75
+ | `by_quarter` | 3-month intervals of the year. |
76
+ | `by_year` | Query by year. Allows integer arg, e.g. `2017`. |
71
77
 
72
78
  ### Relative Scopes
73
79
 
@@ -75,19 +81,21 @@ ByStar also adds scopes which are relative to the current time.
75
81
  Note the `past_*` and `next_*` methods represent a time distance from current time (`Time.zone.now`),
76
82
  and do not strictly end/begin evenly on a calendar week/month/year (unlike `by_*` methods which do.)
77
83
 
78
- * `today` Finds all occurrences on today's date
79
- * `yesterday` Finds all occurrences on yesterday's date
80
- * `tomorrow` Finds all occurrences on tomorrow's date
81
- * `past_day` Prior 24-hour period from current time
82
- * `past_week` Prior 7-day period from current time
83
- * `past_fortnight` Prior 14-day period from current time
84
- * `past_month` Prior 30-day period from current time
85
- * `past_year` Prior 365-day period from current time
86
- * `next_day` Subsequent 24-hour period from current time
87
- * `next_week` Subsequent 7-day period from current time
88
- * `next_fortnight` Subsequent 14-day period from current time
89
- * `next_month` Subsequent 30-day period from current time
90
- * `next_year` Subsequent 365-day period from current time
84
+ | Scope | Meaning |
85
+ | --- | --- |
86
+ | `today` | Finds all occurrences on today's date. |
87
+ | `yesterday` | Finds all occurrences on yesterday's date. |
88
+ | `tomorrow` | Finds all occurrences on tomorrow's date. |
89
+ | `past_day` | Prior 24-hour period from current time. |
90
+ | `past_week` | Prior 7-day period from current time. |
91
+ | `past_fortnight` | Prior 14-day period from current time. |
92
+ | `past_month` | Prior 30-day period from current time. |
93
+ | `past_year` | Prior 365-day period from current time. |
94
+ | `next_day` | Subsequent 24-hour period from current time. |
95
+ | `next_week` | Subsequent 7-day period from current time. |
96
+ | `next_fortnight` | Subsequent 14-day period from current time. |
97
+ | `next_month` | Subsequent 30-day period from current time. |
98
+ | `next_year` | Subsequent 365-day period from current time. |
91
99
 
92
100
  ### Superlative Finders
93
101
 
@@ -126,57 +134,42 @@ By default, ByStar assumes you will use the `created_at` field to query objects
126
134
  You may specify an alternate field on all query methods as follows:
127
135
 
128
136
  ```ruby
129
- Post.by_month("January", field: :updated_at)
137
+ Post.by_month("January", field: :updated_at)
130
138
  ```
131
139
 
132
140
  Alternatively, you may set a default in your model using the `by_star_field` macro:
133
141
 
134
142
  ```ruby
135
- class Post < ActiveRecord::Base
136
- by_star_field :updated_at
137
- end
143
+ class Post < ActiveRecord::Base
144
+ by_star_field :updated_at
145
+ end
138
146
  ```
139
147
 
140
148
  ### Scoping the Query
141
149
 
142
- All ByStar methods (except `oldest`, `newest`, `previous`, `next`) return `ActiveRecord::Relation` and/or
143
- `Mongoid::Criteria` objects, which can be daisy-chained with other scopes/finder methods:
150
+ All ByStar methods (except `oldest`, `newest`, `previous`, `next`) return an `ActiveRecord::Relation`
151
+ (or `Mongoid::Criteria`) which can be daisy-chained with other scopes/finder methods:
144
152
 
145
153
  ```ruby
146
- Post.by_month.your_scope
147
- Post.by_month(1).include(:tags).where("tags.name" => "ruby")
154
+ Post.by_month.your_scope
155
+ Post.by_month(1).include(:tags).where("tags.name" => "ruby")
148
156
  ```
149
157
 
150
158
  Want to count records? Simple:
151
159
 
152
160
  ```ruby
153
- Post.by_month.count
161
+ Post.by_month.count
154
162
  ```
155
163
 
156
- ### :scope Option
164
+ ### Timezone Handling
157
165
 
158
- You may pass a `:scope` option as a Relation or Proc to all ByStar methods like so:
166
+ ByStar date-range finders will use value of `Time.zone` to evaluate the args.
167
+ This may cause unexpected behavior when use Time values in timezones other than `Time.zone`.
159
168
 
160
169
  ```ruby
161
- @post.next(scope: Post.where(category: @post.category))
162
- @post.next(scope: ->{ where(category: 'blog') })
163
- ```
164
-
165
- This is particularly useful for `oldest`, `newest`, `previous`, `next` which return a model instance rather than
166
- a Relation and hence cannot be daisy-chained with other scopes.
167
-
168
- `previous` and `next` support a special feature that the `:scope` option may take the subject record as an argument:
169
-
170
- ```ruby
171
- @post.next(scope: ->(record){ where(category: record.category) })
172
- ```
173
-
174
- You may also set a default scope in the `by_star_field` macro. (It is recommended this be a Proc):
175
-
176
- ```ruby
177
- class Post < ActiveRecord::Base
178
- by_star_field scope: ->{ where(category: 'blog') }
179
- end
170
+ Time.zone = 'Australia/Sydney'
171
+ Post.by_day('2020-04-05 18:00:00 EST')
172
+ #=> Returns Apr 6th, 0:00 until Apr 6th, 23:59 in Sydney timezone.
180
173
  ```
181
174
 
182
175
  ### `:offset` Option
@@ -186,14 +179,16 @@ This is useful in cases where the daily cycle occurs at a time other than midnig
186
179
 
187
180
  For example, if you'd like to find all Posts from 9:00 on 2014-03-05 until 8:59:59.999 on 2014-03-06, you can do:
188
181
 
189
- Post.by_day('2014-03-05', offset: 9.hours)
182
+ ```ruby
183
+ Post.by_day('2014-03-05', offset: 9.hours)
184
+ ```
190
185
 
191
- You may also set a offset scope in the `by_star_field` macro:
186
+ **Note:** When passing `offset` in date finders, it will set the hour, minute, and second on the queried date in order to properly handle DST transitions. Example:
192
187
 
193
188
  ```ruby
194
- class Post < ActiveRecord::Base
195
- by_star_field offset: 9.hours
196
- end
189
+ Time.zone = 'Australia/Sydney'
190
+ Post.by_day('2020-04-05', offset: 9.hours)
191
+ #=> Returns Apr 5th, 09:00 until Apr 6th, 08:59
197
192
  ```
198
193
 
199
194
  ### Timespan Objects
@@ -201,25 +196,39 @@ You may also set a offset scope in the `by_star_field` macro:
201
196
  If your object has both a start and end time, you may pass both params to `by_star_field`:
202
197
 
203
198
  ```ruby
204
- by_star_field :start_time, :end_time
199
+ by_star_field :start_time, :end_time
205
200
  ```
206
201
 
207
202
  By default, ByStar queries will return all objects whose range has any overlap within the desired period (permissive):
208
203
 
209
204
  ```ruby
210
- MultiDayEvent.by_month("January") #=> returns MultiDayEvents that overlap in January,
211
- even if they start in December and/or end in February
205
+ MultiDayEvent.by_month("January")
206
+ #=> returns MultiDayEvents that overlap in January,
207
+ # even if they start in December and/or end in February
208
+ ```
209
+
210
+ ### Timespan Objects: `#at_time`
211
+
212
+ To find all instances of a timespan object which contain a specific time:
213
+
214
+ ```ruby
215
+ Post.at_time(time)
212
216
  ```
213
217
 
218
+ This can be useful to find all currently active instances. Note that object instances which start
219
+ exactly at the given `time` will be included in the result, but instances that end exactly at the given
220
+ `time` will not be.
221
+
214
222
  ### Timespan Objects: `:strict` Option
215
223
 
216
224
  If you'd like to confine results to only those both starting and ending within the given range, use the `:strict` option:
217
225
 
218
226
  ```ruby
219
- MultiDayEvent.by_month("January", :strict => true) #=> returns MultiDayEvents that both start AND end in January
227
+ MultiDayEvent.by_month("January", :strict => true)
228
+ #=> returns MultiDayEvents that both start AND end in January
220
229
  ```
221
230
 
222
- ### Timespan Objects: Database Indexing and `:index_start` Option
231
+ ### Timespan Objects: Database Indexing and `:index_scope` Option
223
232
 
224
233
  In order to ensure query performance on large dataset, you must add an index to the query field (e.g. "created_at") be indexed. ByStar does **not** define indexes automatically.
225
234
 
@@ -228,14 +237,40 @@ If we use a single-sided query, the database will iterate through all items eith
228
237
  This poses a challenge for timespan-type objects which have two fields, i.e. `start_time` and `end_time`.
229
238
  There are two cases to consider:
230
239
 
231
- 1) Timespan with `:strict` option, e.g. "start_time >= X and end_time <= Y".
240
+ 1) Timespan with `:strict` option, e.g. `start_time >= X and end_time <= Y`.
232
241
 
233
- Given that this gem requires start_time >= end_time, we add the converse constraint "start_time <= Y and end_time >= X" to ensure both fields are double-sided, i.e. an index can be used on either field.
242
+ Given that this gem requires `start_time >= end_time`, we add the converse constraint `start_time <= Y and end_time >= X`
243
+ to ensure both fields are double-sided, i.e. an index can be used on either field.
234
244
 
235
245
  2) Timespan without `:strict` option, e.g. "start_time < Y and end_time > X".
236
246
 
237
- This is not yet supported but will be soon.
247
+ Here we need to add a condition `start_time >= X` to ensure `start_time` is bounded on both sides.
248
+ To achieve this, we allow an `:index_scope` option which is the minimum "strict" bound on the querying range,
249
+ in other words, it is an assumption about the maximum timespan of objects.
250
+
251
+ `:index_scope` supports multiple value types:
252
+
253
+ | `:index_scope` Value | Meaning |
254
+ | --- | --- |
255
+ | `nil` or `false` | No constraint set; query will be one-sided (default, but not recommended) |
256
+ | `Date` or `Time`, etc. | A fixed point in time |
257
+ | `ActiveSupport::Duration` (e.g. `1.month`) | The duration value will be subtracted from the start of the range. In other words, a value of `1.month` would imply the longest possible object in the database is no longer than `1.month`. |
258
+ | `Numeric` | Will be converted to seconds, then handled the same as `ActiveSupport::Duration` |
259
+ | `:beginning_of_day` (`Symbol` literal) |
260
+ | `Proc<Range, Hash(options)>` | A proc which evaluates to one of the above types. Args are `(start_time, end_time, options)` |
261
+
262
+ An example settings of `:index_scope`:
238
263
 
264
+ ```
265
+ # The maximum possible object length is 5 hours.
266
+ by_star index_scope: 5.hours
267
+
268
+ # Objects are guaranteed to start within the same month, with some offset.
269
+ by_star index_scope: ->(start_time, end_time, options){ start_time.beginning_of_month + (options[:offset] || 0) }
270
+
271
+ # The maximum possible object length half the range being queried.
272
+ by_star index_scope: ->(start_time, end_time, options){ ((start_time - end_time)*0.5).seconds }
273
+ ```
239
274
 
240
275
  ### Chronic Support
241
276
 
@@ -244,7 +279,6 @@ strings in all ByStar finder methods. Otherwise, the Ruby `Time.parse` kernel me
244
279
 
245
280
  As of ByStar 2.2.0, you must explicitly include `gem 'chronic'` into your Gemfile in order to use Chronic.
246
281
 
247
-
248
282
  ## Advanced Usage
249
283
 
250
284
  ### between_times
@@ -252,41 +286,43 @@ As of ByStar 2.2.0, you must explicitly include `gem 'chronic'` into your Gemfil
252
286
  To find records between two times:
253
287
 
254
288
  ```ruby
255
- Post.between_times(time1, time2)
289
+ Post.between_times(time1, time2)
256
290
  ```
257
291
 
258
292
  You use a Range like so:
259
293
 
260
294
  ```ruby
261
- Post.between_times(time1..time2)
295
+ Post.between_times(time1..time2)
262
296
  ```
263
297
 
264
298
  Also works with dates - WARNING: there are currently some caveats see [Issue #49](https://github.com/radar/by_star/issues/49):
265
299
 
266
300
  ```ruby
267
- Post.between_times(date1, date2)
301
+ Post.between_times(date1, date2)
268
302
  ```
269
303
 
304
+ It will query records from `date1` (00:00:00 Hrs) until `date2` (23:59:59 Hrs).
305
+
270
306
  ### before and after
271
307
 
272
308
  To find all posts before / after the current time:
273
309
 
274
310
  ```ruby
275
- Post.before
276
- Post.after
311
+ Post.before
312
+ Post.after
277
313
  ```
278
314
 
279
315
  To find all posts before certain time or date:
280
316
 
281
317
  ```ruby
282
- Post.before(Date.today + 2)
283
- Post.after(Time.now + 5.days)
318
+ Post.before(Date.today + 2)
319
+ Post.after(Time.now + 5.days)
284
320
  ```
285
321
 
286
322
  You can also pass a string:
287
323
 
288
324
  ```ruby
289
- Post.before("next tuesday")
325
+ Post.before("next tuesday")
290
326
  ```
291
327
 
292
328
  For Time-Range type objects, only the start time is considered for `before` and `after`.
@@ -296,15 +332,15 @@ For Time-Range type objects, only the start time is considered for `before` and
296
332
  To find the prior/subsequent record to a model instance, `previous`/`next` on it:
297
333
 
298
334
  ```ruby
299
- Post.last.previous
300
- Post.first.next
335
+ Post.last.previous
336
+ Post.first.next
301
337
  ```
302
338
 
303
339
  You can specify a field also:
304
340
 
305
341
  ```ruby
306
- Post.last.previous(field: "published_at")
307
- Post.first.next(field: "published_at")
342
+ Post.last.previous(field: "published_at")
343
+ Post.first.next(field: "published_at")
308
344
  ```
309
345
 
310
346
  For Time-Range type objects, only the start time is considered for `previous` and `next`.
@@ -314,19 +350,19 @@ For Time-Range type objects, only the start time is considered for `previous` an
314
350
  To find records from the current year, simply call the method without any arguments:
315
351
 
316
352
  ```ruby
317
- Post.by_year
353
+ Post.by_year
318
354
  ```
319
355
 
320
356
  To find records based on a year you can pass it a two or four digit number:
321
357
 
322
358
  ```ruby
323
- Post.by_year(09)
359
+ Post.by_year(09)
324
360
  ```
325
361
 
326
362
  This will return all posts in 2009, whereas:
327
363
 
328
364
  ```ruby
329
- Post.by_year(99)
365
+ Post.by_year(99)
330
366
  ```
331
367
 
332
368
  will return all the posts in the year 1999.
@@ -334,8 +370,8 @@ will return all the posts in the year 1999.
334
370
  You can also specify the full year:
335
371
 
336
372
  ```ruby
337
- Post.by_year(2009)
338
- Post.by_year(1999)
373
+ Post.by_year(2009)
374
+ Post.by_year(1999)
339
375
  ```
340
376
 
341
377
  ### by_month
@@ -343,7 +379,7 @@ You can also specify the full year:
343
379
  If you know the number of the month you want:
344
380
 
345
381
  ```ruby
346
- Post.by_month(1)
382
+ Post.by_month(1)
347
383
  ```
348
384
 
349
385
  This will return all posts in the first month (January) of the current year.
@@ -351,7 +387,7 @@ This will return all posts in the first month (January) of the current year.
351
387
  If you like being verbose:
352
388
 
353
389
  ```ruby
354
- Post.by_month("January")
390
+ Post.by_month("January")
355
391
  ```
356
392
 
357
393
  This will return all posts created in January of the current year.
@@ -359,13 +395,13 @@ This will return all posts created in January of the current year.
359
395
  If you want to find all posts in January of last year just do
360
396
 
361
397
  ```ruby
362
- Post.by_month(1, year: 2007)
398
+ Post.by_month(1, year: 2007)
363
399
  ```
364
400
 
365
401
  or
366
402
 
367
403
  ```ruby
368
- Post.by_month("January", year: 2007)
404
+ Post.by_month("January", year: 2007)
369
405
  ```
370
406
 
371
407
  This will perform a find using the column you've specified.
@@ -373,7 +409,7 @@ This will perform a find using the column you've specified.
373
409
  If you have a Time object you can use it to find the posts:
374
410
 
375
411
  ```ruby
376
- Post.by_month(Time.local(2012, 11, 24))
412
+ Post.by_month(Time.local(2012, 11, 24))
377
413
  ```
378
414
 
379
415
  This will find all the posts in November 2012.
@@ -383,7 +419,7 @@ This will find all the posts in November 2012.
383
419
  Finds records for a given month as shown on a calendar. Includes all the results of `by_month`, plus any results which fall in the same week as the first and last of the month. Useful for working with UI calendars which show rows of weeks.
384
420
 
385
421
  ```ruby
386
- Post.by_calendar_month
422
+ Post.by_calendar_month
387
423
  ```
388
424
 
389
425
  Parameter behavior is otherwise the same as `by_month`. Also, `:start_day` option is supported to specify the start day of the week (`:monday`, `:tuesday`, etc.)
@@ -395,25 +431,25 @@ Fortnight numbering starts at 0. The beginning of a fortnight is Monday, 12am.
395
431
  To find records from the current fortnight:
396
432
 
397
433
  ```ruby
398
- Post.by_fortnight
434
+ Post.by_fortnight
399
435
  ```
400
436
 
401
437
  To find records based on a fortnight, you can pass in a number (representing the fortnight number) or a time object:
402
438
 
403
439
  ```ruby
404
- Post.by_fortnight(18)
440
+ Post.by_fortnight(18)
405
441
  ```
406
442
 
407
443
  This will return all posts in the 18th fortnight of the current year.
408
444
 
409
445
  ```ruby
410
- Post.by_fortnight(18, year: 2012)
446
+ Post.by_fortnight(18, year: 2012)
411
447
  ```
412
448
 
413
449
  This will return all posts in the 18th fortnight week of 2012.
414
450
 
415
451
  ```ruby
416
- Post.by_fortnight(Time.local(2012,1,1))
452
+ Post.by_fortnight(Time.local(2012,1,1))
417
453
  ```
418
454
 
419
455
  This will return all posts from the first fortnight of 2012.
@@ -425,29 +461,29 @@ Week numbering starts at 0, and cweek numbering starts at 1 (same as `Date#cweek
425
461
  To find records from the current week:
426
462
 
427
463
  ```ruby
428
- Post.by_week
429
- Post.by_cweek # same result
464
+ Post.by_week
465
+ Post.by_cweek # same result
430
466
  ```
431
467
 
432
468
  This will return all posts in the 37th week of the current year (remember week numbering starts at 0):
433
469
 
434
470
  ```ruby
435
- Post.by_week(36)
436
- Post.by_cweek(37) # same result
471
+ Post.by_week(36)
472
+ Post.by_cweek(37) # same result
437
473
  ```
438
474
 
439
475
  This will return all posts in the 37th week of 2012:
440
476
 
441
477
  ```ruby
442
- Post.by_week(36, year: 2012)
443
- Post.by_cweek(37, year: 2012) # same result
478
+ Post.by_week(36, year: 2012)
479
+ Post.by_cweek(37, year: 2012) # same result
444
480
  ```
445
481
 
446
482
  This will return all posts in the week which contains Jan 1, 2012:
447
483
 
448
484
  ```ruby
449
- Post.by_week(Time.local(2012,1,1))
450
- Post.by_cweek(Time.local(2012,1,1)) # same result
485
+ Post.by_week(Time.local(2012,1,1))
486
+ Post.by_cweek(Time.local(2012,1,1)) # same result
451
487
  ```
452
488
 
453
489
  You may pass in a `:start_day` option (`:monday`, `:tuesday`, etc.) to specify the starting day of the week. This may also be configured in Rails.
@@ -457,7 +493,7 @@ You may pass in a `:start_day` option (`:monday`, `:tuesday`, etc.) to specify t
457
493
  If the time passed in (or the time now is a weekend) it will return posts from 0:00 Saturday to 23:59:59 Sunday. If the time is a week day, it will show all posts for the coming weekend.
458
494
 
459
495
  ```ruby
460
- Post.by_weekend(Time.now)
496
+ Post.by_weekend(Time.now)
461
497
  ```
462
498
 
463
499
  ### by_day and today
@@ -465,20 +501,20 @@ If the time passed in (or the time now is a weekend) it will return posts from 0
465
501
  To find records for today:
466
502
 
467
503
  ```ruby
468
- Post.by_day
469
- Post.today
504
+ Post.by_day
505
+ Post.today
470
506
  ```
471
507
 
472
508
  To find records for a certain day:
473
509
 
474
510
  ```ruby
475
- Post.by_day(Time.local(2012, 1, 1))
511
+ Post.by_day(Time.local(2012, 1, 1))
476
512
  ```
477
513
 
478
514
  You can also pass a string:
479
515
 
480
516
  ```ruby
481
- Post.by_day("next tuesday")
517
+ Post.by_day("next tuesday")
482
518
  ```
483
519
 
484
520
  This will return all posts for the given day.
@@ -490,42 +526,41 @@ Finds records by 3-month quarterly period of year. Quarter numbering starts at 1
490
526
  To find records from the current quarter:
491
527
 
492
528
  ```ruby
493
- Post.by_quarter
529
+ Post.by_quarter
494
530
  ```
495
531
 
496
532
  To find records based on a quarter, you can pass in a number (representing the quarter number) or a time object:
497
533
 
498
534
  ```ruby
499
- Post.by_quarter(4)
535
+ Post.by_quarter(4)
500
536
  ```
501
537
 
502
538
  This will return all posts in the 4th quarter of the current year.
503
539
 
504
540
  ```ruby
505
- Post.by_quarter(2, year: 2012)
541
+ Post.by_quarter(2, year: 2012)
506
542
  ```
507
543
 
508
544
  This will return all posts in the 2nd quarter of 2012.
509
545
 
510
546
  ```ruby
511
- Post.by_week(Time.local(2012,1,1))
547
+ Post.by_week(Time.local(2012,1,1))
512
548
  ```
513
549
 
514
550
  This will return all posts from the first quarter of 2012.
515
551
 
516
-
517
552
  ## Version Support
518
553
 
519
554
  ByStar is tested against the following versions:
520
555
 
521
- * Ruby 1.9.3+
522
- * Rails/ActiveRecord 3.0+
523
- * Mongoid 3.0+
556
+ * Ruby 2.0.0+
557
+ * Rails/ActiveRecord 3.2+
558
+ * Mongoid 3.1+
524
559
 
525
560
  Note that ByStar automatically adds the following version compatibility shims:
526
561
 
527
- * ActiveSupport 3.x: `Date#to_time_in_current_zone` is aliased to `Date#in_time_zone` from version 4+
528
- * Mongoid 3.x: Adds support for `Criteria#reorder` method from version 4+
562
+ * ActiveSupport 3.x: Add `Time/Date/DateTime#in_time_zone` (as an alias to `#to_time_in_current_zone`) for compatibility with Rails 4+.
563
+ * Mongoid 3.x: Adds `Criteria#reorder` method from Mongoid 4.
529
564
 
530
565
 
531
566
  ## Testing
@@ -534,11 +569,15 @@ Note that ByStar automatically adds the following version compatibility shims:
534
569
 
535
570
  Specify a database by supplying a `DB` environmental variable:
536
571
 
537
- `bundle exec rake spec DB=sqlite`
572
+ ```bash
573
+ bundle exec rake spec DB=sqlite
574
+ ```
538
575
 
539
576
  You can also take an ORM-specific test task for a ride:
540
577
 
541
- `bundle exec rake spec:active_record`
578
+ ```bash
579
+ bundle exec rake spec:active_record
580
+ ```
542
581
 
543
582
  Have an Active Record or Mongoid version in mind? Set the environment variables
544
583
  `ACTIVE_RECORD_VERSION` and `MONGOID_VERSION` to a version of your choice. A
data/UPGRADING CHANGED
@@ -1,6 +1,4 @@
1
1
  Upgrading ByStar
2
2
  ----------------
3
3
 
4
- * Chronic gem (used for time string parsing) has been removed as a hard dependency for ByStar,
5
- however it is still supported. If you would like to use Chronic with ByStar, please explicitly
6
- include `gem chronic` into your Gemfile.
4
+ * As of version 4.0.0, ByStar changes the way it handles `Date` arg to the `#between_times` method. If a `Date` is given as the second (end) arg, the query will use `Date.end_of_day` to include all time values which fall inside that date.
data/by_star.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.post_install_message = File.read('UPGRADING') if File.exists?('UPGRADING')
16
16
 
17
- s.add_dependency "activesupport", "> 3"
17
+ s.add_dependency "activesupport", ">= 3.2.0"
18
18
 
19
19
  s.add_development_dependency "chronic"
20
20
  s.add_development_dependency "bundler"
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "activerecord"
23
23
  s.add_development_dependency "mongoid"
24
24
  s.add_development_dependency "pg"
25
- s.add_development_dependency "mysql2", "~> 0.3.10"
25
+ s.add_development_dependency "mysql2"
26
26
  s.add_development_dependency "rspec-rails", "~> 3.1"
27
27
  s.add_development_dependency "timecop", "~> 0.3"
28
28
  s.add_development_dependency "pry"