by_star 2.1.0.beta2 → 2.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.gitignore +5 -4
  2. data/.travis.yml +35 -25
  3. data/CHANGELOG.md +21 -0
  4. data/Gemfile +25 -4
  5. data/MIT-LICENSE +20 -20
  6. data/{README.markdown → README.md} +414 -348
  7. data/Rakefile +18 -2
  8. data/UPGRADING +10 -0
  9. data/by_star.gemspec +32 -31
  10. data/cleaner.rb +24 -24
  11. data/lib/by_star.rb +15 -71
  12. data/lib/by_star/base.rb +53 -0
  13. data/lib/by_star/between.rb +80 -0
  14. data/lib/by_star/directional.rb +21 -0
  15. data/lib/by_star/kernel.rb +41 -0
  16. data/lib/by_star/normalization.rb +118 -0
  17. data/lib/by_star/orm/active_record/by_star.rb +52 -0
  18. data/lib/by_star/orm/mongoid/by_star.rb +59 -0
  19. data/lib/by_star/version.rb +3 -3
  20. data/spec/database.yml +15 -15
  21. data/spec/fixtures/active_record/models.rb +6 -13
  22. data/spec/fixtures/active_record/schema.rb +11 -36
  23. data/spec/fixtures/mongoid/models.rb +15 -65
  24. data/spec/fixtures/shared/seeds.rb +16 -35
  25. data/spec/integration/active_record/active_record_spec.rb +50 -0
  26. data/spec/integration/mongoid/mongoid_spec.rb +43 -0
  27. data/spec/integration/shared/by_calendar_month.rb +55 -0
  28. data/spec/integration/shared/by_day.rb +84 -0
  29. data/spec/integration/shared/by_direction.rb +55 -0
  30. data/spec/integration/shared/by_fortnight.rb +48 -0
  31. data/spec/integration/shared/by_month.rb +50 -0
  32. data/spec/integration/shared/by_quarter.rb +49 -0
  33. data/spec/integration/shared/by_week.rb +54 -0
  34. data/spec/integration/shared/by_weekend.rb +49 -0
  35. data/spec/integration/shared/by_year.rb +48 -0
  36. data/spec/integration/shared/offset_parameter.rb +31 -0
  37. data/spec/spec_helper.rb +29 -35
  38. data/spec/unit/kernel_time_spec.rb +57 -0
  39. data/spec/unit/normalization_spec.rb +255 -0
  40. metadata +131 -56
  41. data/Gemfile.lock +0 -94
  42. data/lib/by_star/by_day.rb +0 -34
  43. data/lib/by_star/by_direction.rb +0 -52
  44. data/lib/by_star/by_fortnight.rb +0 -58
  45. data/lib/by_star/by_month.rb +0 -47
  46. data/lib/by_star/by_quarter.rb +0 -32
  47. data/lib/by_star/by_week.rb +0 -32
  48. data/lib/by_star/by_weekend.rb +0 -20
  49. data/lib/by_star/by_year.rb +0 -62
  50. data/lib/by_star/instance_methods.rb +0 -13
  51. data/lib/by_star/time_ext.rb +0 -21
  52. data/lib/mongoid/by_star.rb +0 -83
  53. data/spec/by_star/active_record/active_record_spec.rb +0 -50
  54. data/spec/by_star/mongoid/mongoid_spec.rb +0 -44
  55. data/spec/by_star/shared/by_day.rb +0 -62
  56. data/spec/by_star/shared/by_direction.rb +0 -85
  57. data/spec/by_star/shared/by_fortnight.rb +0 -47
  58. data/spec/by_star/shared/by_month.rb +0 -109
  59. data/spec/by_star/shared/by_quarter.rb +0 -33
  60. data/spec/by_star/shared/by_week.rb +0 -41
  61. data/spec/by_star/shared/by_weekend.rb +0 -13
  62. data/spec/by_star/shared/by_year.rb +0 -54
  63. data/spec/time_ext_spec.rb +0 -10
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
- tmp
2
- spec/fixtures/database.yml
3
- pkg
4
- by_star.sqlite3
1
+ tmp
2
+ spec/fixtures/database.yml
3
+ pkg
4
+ by_star.sqlite3
5
+ Gemfile.lock
@@ -1,25 +1,35 @@
1
- before_script:
2
- - "mysql -e 'create database by_star_test;'"
3
- - "psql -c 'create database by_star_test;' -U postgres"
4
-
5
- env:
6
- - DB=sqlite
7
- - DB=mysql
8
- - DB=postgres
9
-
10
- script: "DISPLAY=:99.0 bundle exec rspec spec/by_star"
11
-
12
- notifications:
13
- email:
14
- - radarlistener@gmail.com
15
-
16
- branches:
17
- only:
18
- - master
19
-
20
- rvm:
21
- - 1.8.7
22
- - 1.9.3
23
- - 1.9.2
24
-
25
- services: mongodb
1
+ before_script:
2
+ - "mysql -e 'create database by_star_test;'"
3
+ - "psql -c 'create database by_star_test;' -U postgres"
4
+
5
+ env:
6
+ - DB=sqlite
7
+ - DB=mysql
8
+ - DB=postgres
9
+ - DB=mongodb
10
+ - ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master DB=sqlite
11
+ - ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master DB=mysql
12
+ - ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master DB=postgres
13
+ - ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master DB=mongodb
14
+
15
+ notifications:
16
+ email:
17
+ - radarlistener@gmail.com
18
+
19
+ branches:
20
+ only:
21
+ - master
22
+
23
+ rvm:
24
+ - 1.9.3
25
+ - 2.0.0
26
+ - 2.1.0
27
+ - rbx
28
+ - jruby
29
+
30
+ matrix:
31
+ allow_failures:
32
+ - rvm: rbx
33
+ - rvm: jruby
34
+
35
+ services: mongodb
@@ -0,0 +1,21 @@
1
+ # CHANGELOG
2
+
3
+ ## v2.2.0
4
+
5
+ * Begin tracking CHANGELOG
6
+ * Drop official support for Ruby <= 1.9.2
7
+ * Add Ruby 2.1.0, Rubinius, and JRuby to Travis
8
+ * Decouple gem from ActiveRecord, and put ActiveRecord and Mongoid specific methods in ORM modules.
9
+ * Consolidate all normalization/parsing functions into new Normalization module
10
+ * Remove meta-programming methods, e.g. `send("by_week_#{time_klass}")`
11
+ * Support matching timespan-type objects with distinct start and end times (previously only point-in-time matching was supported)
12
+ * Make Chronic gem optional; use it only if user has included it externally
13
+ * `by_week` always returns a calendar week (i.e. beginning Monday or as specified by Rails setting), regardless of whether Date or Fixnum is given as a parameter.
14
+ * `by_week` and `by_calendar_month` now supports optional `:start_day` option (:monday, :tuesday, etc)
15
+ * Separate `by_calendar_month` into it's own class
16
+ * Rename `between` method to `between_times` internally, as Mongoid already defines `between`. ActiveRecord has an alias of `between` so interface stays consistent.
17
+ * Add `:offset` option to all query methods, in order to offset the time the day begins/ends (for example supposing business cycle begins at 8:00 each day until 7:59:59 the next day)
18
+ * `by_weekend` can now take a fixnum (parsing logic is same as by_week)
19
+ * Two-digit year now considers 70 to be 1970, and 69 to be 2069 (was previously 40 -> 1940)
20
+ * Add Time kernel extensions for fortnight and calendar_month
21
+ * Add Johnny Shields as a gem co-author
data/Gemfile CHANGED
@@ -1,4 +1,25 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in by_star.gemspec
4
- gemspec
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in by_star.gemspec
4
+ gemspec
5
+
6
+ active_record_version = ENV['ACTIVE_RECORD_VERSION'] || 'default'
7
+
8
+ active_record_opts =
9
+ case active_record_version
10
+ when 'master' then {github: 'rails/rails'}
11
+ when 'default' then '~> 3.0'
12
+ else "~> #{active_record_version}"
13
+ end
14
+
15
+ mongoid_version = ENV['MONGOID_VERSION'] || 'default'
16
+
17
+ mongoid_opts =
18
+ case mongoid_version
19
+ when 'master' then {github: 'mongoid/mongoid'}
20
+ when 'default' then '~> 3.0'
21
+ else "~> #{mongoid_version}"
22
+ end
23
+
24
+ gem 'activerecord', active_record_opts
25
+ gem 'mongoid', mongoid_opts
@@ -1,20 +1,20 @@
1
- Copyright (c) 2008 [name of plugin creator]
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2008 Ryan Bigg
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,348 +1,414 @@
1
- # by_*
2
-
3
-
4
- by_* (by_star) is a plugin that allows you to find ActiveRecord and/or Mongoid objects given certain date objects.
5
-
6
- ## Installation
7
-
8
- Install this gem by adding this to your Gemfile:
9
-
10
- ```ruby
11
- gem 'by_star', :git => "git://github.com/radar/by_star"
12
- ```
13
-
14
- Then run `bundle install`.
15
-
16
- If you are using ActiveRecord, you're done!
17
-
18
- Mongoid users, please include the Mongoid::ByStar module for each model you wish to use the functionality. This is the convention among Mongoid plugins.
19
-
20
- ```ruby
21
- class MyModel
22
- include Mongoid::Document
23
- include Mongoid::ByStar
24
- ```
25
-
26
- ## What it does
27
-
28
- This was originally crafted for only finding objects within a given month, but now has extended out to much more. It now supports finding objects for:
29
-
30
- * A given year
31
- * A given month
32
- * A given fortnight
33
- * A given week
34
- * A given weekend
35
- * A given day
36
- * A given quarter
37
- * The weeks of a given month as shown on a calendar
38
- * The current weekend
39
- * The current work week
40
- * The Past
41
- * The Future
42
- * Between certain times
43
- * Before a specific record
44
- * After a specific record
45
-
46
- All methods return scopes. I love these. You love these. Everybody loves these.
47
-
48
- It also allows you to do nested finds on the records returned which I personally think is the coolest feature of the whole plugin:
49
-
50
- Post.by_month(1).include(:tags).where("tags.name" => "ruby")
51
-
52
- If you're not using the standard `created_at` field: don't worry! I've covered that scenario too.
53
-
54
- ## Scoping the find
55
-
56
- You can treat all `by_*` methods exactly how you would treat normal, every-day ActiveRecord scopes. This is because all `by_*` methods return `ActiveRecord::Relation` objects, with the exception of `previous` and `next`, which return a single record. You can call them like this:
57
-
58
- Post.by_month.your_scope
59
-
60
- Where `my_special_scope` is a `named_scope` you have specified.
61
-
62
- You can also call typical `ActiveRecord::Relation` methods on the `by_*` methods (like I showed before):
63
-
64
- Post.by_month.include(:tags).where("tags.name" => "ruby")
65
-
66
- Want to count records? Simple:
67
-
68
- Post.by_month.count
69
-
70
-
71
- ## By Year (`by_year`)
72
-
73
- To find records from the current year, simply call the method without any arguments:
74
-
75
- Post.by_year
76
-
77
- To find records based on a year you can pass it a two or four digit number:
78
-
79
- Post.by_year(09)
80
-
81
- This will return all posts in 2009, whereas:
82
-
83
- Post.by_year(99)
84
-
85
- will return all the posts in the year 1999.
86
-
87
- You can also specify the full year:
88
-
89
- Post.by_year(2009)
90
- Post.by_year(1999)
91
-
92
- ## By Month (`by_month`)
93
-
94
- If you know the number of the month you want:
95
-
96
- Post.by_month(1)
97
-
98
- This will return all posts in the first month (January) of the current year.
99
-
100
- If you like being verbose:
101
-
102
- Post.by_month("January")
103
-
104
- This will return all posts created in January of the current year.
105
-
106
- If you want to find all posts in January of last year just do
107
-
108
- Post.by_month(1, :year => 2007)
109
-
110
- or
111
-
112
- Post.by_month("January", :year => 2007)
113
-
114
- This will perform a find using the column you've specified.
115
-
116
- If you have a Time object you can use it to find the posts:
117
-
118
- Post.by_month(Time.local(2012, 11, 24))
119
-
120
- This will find all the posts in November 2012.
121
-
122
- ## By Calendar Month (`by_calendar_month`)
123
-
124
- 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.
125
-
126
- Post.by_calendar_month
127
-
128
- Parameter behavior is otherwise the same as `by_month`
129
-
130
- ## By Fortnight (`by_fortnight`)
131
-
132
- Fortnight numbering starts at 0. The beginning of a fortnight is Monday, 12am.
133
-
134
- To find records from the current fortnight:
135
-
136
- Post.by_fortnight
137
-
138
- To find records based on a fortnight, you can pass in a number (representing the fortnight number) or a time object:
139
-
140
- Post.by_fortnight(18)
141
-
142
- This will return all posts in the 18th fortnight of the current year.
143
-
144
- Post.by_fortnight(18, :year => 2012)
145
-
146
- This will return all posts in the 18th fortnight week of 2012.
147
-
148
- Post.by_fortnight(Time.local(2012,1,1))
149
-
150
- This will return all posts from the first fortnight of 2012.
151
-
152
- ## By Week (`by_week`)
153
-
154
- Week numbering starts at 0. The beginning of a week is Monday, 12am.
155
-
156
- To find records from the current week:
157
-
158
- Post.by_week
159
-
160
- To find records based on a week, you can pass in a number (representing the week number) or a time object:
161
-
162
- Post.by_week(36)
163
-
164
- This will return all posts in the 37th week of the current year (remember week numbering starts at 0).
165
-
166
- Post.by_week(36, :year => 2012)
167
-
168
- This will return all posts in the 37th week of 2012.
169
-
170
- Post.by_week(Time.local(2012,1,1))
171
-
172
- This will return all posts from the first week of 2012.
173
-
174
- ## By Weekend (`by_weekend`)
175
-
176
- If the time passed in (or the time now is a weekend) it will return posts from 12am Saturday to 11:59:59PM Sunday. If the time is a week day, it will show all posts for the coming weekend.
177
-
178
- Post.by_weekend(Time.now)
179
-
180
- ## By Day (`by_day` or `today`)
181
-
182
- To find records for today:
183
-
184
- Post.by_day
185
- Post.today
186
-
187
- To find records for a certain day:
188
-
189
- Post.by_day(Time.local(2012, 1, 1))
190
-
191
- You can also pass a string:
192
-
193
- Post.by_day("next tuesday")
194
-
195
- This will return all posts for the given day.
196
-
197
- ## By Quarter (`by_quarter`)
198
-
199
- Finds records by 3-month quarterly period of year. Quarter numbering starts at 1. The four quarters of the year begin on Jan 1, Apr 1, Jul 1, and Oct 1 respectively.
200
-
201
- To find records from the current quarter:
202
-
203
- Post.by_quarter
204
-
205
- To find records based on a quarter, you can pass in a number (representing the quarter number) or a time object:
206
-
207
- Post.by_quarter(4)
208
-
209
- This will return all posts in the 4th quarter of the current year.
210
-
211
- Post.by_quarter(2, :year => 2012)
212
-
213
- This will return all posts in the 2nd quarter of 2012.
214
-
215
- Post.by_week(Time.local(2012,1,1))
216
-
217
- This will return all posts from the first quarter of 2012.
218
-
219
- ## Tomorrow (`tomorrow`)
220
-
221
- *This method has been shown to be shifty when passed a `Date` object, it is recommended that you pass it an `ActiveSupport::TimeWithZone` object instead.*
222
-
223
- To find all posts from the day after the current date:
224
-
225
- Post.tomorrow
226
-
227
- To find all posts after a given Date or Time object:
228
-
229
- Post.tomorrow(Date.today + 2)
230
- Post.tomorrow(Time.now + 5.days)
231
-
232
- You can also pass a string:
233
-
234
- Post.tomorrow("next tuesday")
235
-
236
- ## Yesterday (`yesterday`)
237
-
238
- *This method has been shown to be shifty when passed a `Date` object, it is recommended that you pass it an `ActiveSupport::TimeWithZone` object instead.*
239
-
240
- To find all posts from the day before the current date:
241
-
242
- Post.yesterday
243
-
244
- To find all posts before a given Date or Time object:
245
-
246
- Post.yesterday(Date.today + 2)
247
- Post.yesterday(Time.now + 5.days)
248
-
249
- You can also pass a string:
250
-
251
- Post.yesterday("next tuesday")
252
-
253
- ## Before (`before`)
254
-
255
- To find all posts before the current time:
256
-
257
- Post.before
258
-
259
- To find all posts before certain time or date:
260
-
261
- Post.before(Date.today + 2)
262
- Post.before(Time.now + 5.days)
263
-
264
- You can also pass a string:
265
-
266
- Post.before("next tuesday")
267
-
268
- ## After (`after`)
269
-
270
- To find all posts after the current time:
271
-
272
- Post.after
273
-
274
- To find all posts after certain time or date:
275
-
276
- Post.after(Date.today + 2)
277
- Post.after(Time.now + 5.days)
278
-
279
- You can also pass a string:
280
-
281
- Post.after("next tuesday")
282
-
283
- ## Between (`between` or `between_times`)
284
-
285
- To find records between two times:
286
-
287
- Post.between(time1, time2)
288
-
289
- Also works with dates:
290
-
291
- Post.between(date1, date2)
292
-
293
- `between_times` is an alias for `between`:
294
-
295
- Post.between_times(time1, time2) #=> results identical to above
296
-
297
- ## Previous (`previous`)
298
-
299
- To find the record prior to this one call `previous` on any model instance:
300
-
301
- Post.last.previous
302
-
303
- You can specify a field also:
304
-
305
- Post.last.previous("published_at")
306
-
307
- ## Next (`next`)
308
-
309
- To find the record after this one call `next` on any model instance:
310
-
311
- Post.last.next
312
-
313
- You can specify a field also:
314
-
315
- Post.last.next("published_at")
316
-
317
- ## Not using created_at? No worries!
318
-
319
- If your database uses something other than `created_at` for storing a timestamp, you can specify the field option like this:
320
-
321
- Post.by_month("January", :field => :something_else)
322
-
323
- All methods support this extra option.
324
-
325
- Or if you're doing it all the time on your model, then it's best to use `by_star_field` at the top of your model:
326
-
327
- class Post < ActiveRecord::Base
328
- by_star_field :something_else
329
- end
330
-
331
- ## Mongoid
332
-
333
- Mongoid is only tested/supported on version 3.0+
334
-
335
- ## Collaborators
336
-
337
- Thanks to Thomas Sinclair for the original bump for implementing it. I would like to thank #rubyonrails for their support and the following people:
338
-
339
- * Mislav Marohnic
340
- * August Lilleas (leethal)
341
- * gte351s
342
- * Sam Elliott (lenary)
343
- * The people who created Chronic
344
- * Erik Fonselius
345
-
346
- ## Suggestions?
347
-
348
- If you have suggestions, please contact me at radarlistener@gmail.com
1
+ # by_*
2
+
3
+ [![Build Status](https://travis-ci.org/radar/by_star.png)](https://travis-ci.org/radar/by_star)
4
+ [![Code Climate](https://codeclimate.com/github/radar/by_star.png)](https://codeclimate.com/github/radar/by_star)
5
+
6
+ by_* (by_star) is a plugin that allows you to find ActiveRecord and/or Mongoid objects given certain date objects.
7
+
8
+
9
+ ## Installation
10
+
11
+ Install this gem by adding this to your Gemfile:
12
+
13
+ ```ruby
14
+ gem 'by_star', :git => "git://github.com/radar/by_star"
15
+ ```
16
+
17
+ Then run `bundle install`.
18
+
19
+ If you are using ActiveRecord, you're done!
20
+
21
+ Mongoid users, please include the Mongoid::ByStar module for each model you wish to use the functionality. This is the convention among Mongoid plugins.
22
+
23
+ ```ruby
24
+ class MyModel
25
+ include Mongoid::Document
26
+ include Mongoid::ByStar
27
+ ```
28
+
29
+ ## What it does
30
+
31
+ This was originally crafted for only finding objects within a given month, but now has extended out to much more. It now supports finding objects for:
32
+
33
+ * A given year
34
+ * A given month
35
+ * A given fortnight
36
+ * A given week
37
+ * A given weekend
38
+ * A given day
39
+ * A given quarter
40
+ * The weeks of a given month as shown on a calendar
41
+ * The current weekend
42
+ * The current work week
43
+ * The Past
44
+ * The Future
45
+ * Between certain times
46
+ * Before a specific record
47
+ * After a specific record
48
+
49
+ All methods return scopes. I love these. You love these. Everybody loves these.
50
+
51
+ It also allows you to do nested finds on the records returned which I personally think is the coolest feature of the whole plugin:
52
+
53
+ Post.by_month(1).include(:tags).where("tags.name" => "ruby")
54
+
55
+ If you're not using the standard `created_at` field: don't worry! I've covered that scenario too.
56
+
57
+ ## Scoping the find
58
+
59
+ You can treat all `by_*` methods exactly how you would treat normal, every-day ActiveRecord scopes. This is because all `by_*` methods return `ActiveRecord::Relation` objects, with the exception of `previous` and `next`, which return a single record. You can call them like this:
60
+
61
+ Post.by_month.your_scope
62
+
63
+ Where `my_special_scope` is a `named_scope` you have specified.
64
+
65
+ You can also call typical `ActiveRecord::Relation` methods on the `by_*` methods (like I showed before):
66
+
67
+ Post.by_month.include(:tags).where("tags.name" => "ruby")
68
+
69
+ Want to count records? Simple:
70
+
71
+ Post.by_month.count
72
+
73
+ ## Time-Range Type Objects
74
+
75
+ If your object has both a start and end time, you may pass both params to `by_star_field`:
76
+
77
+ by_star_field :start_time, :end_time
78
+
79
+ By default, ByStar queries will return all objects whose range has any overlap within the desired period (permissive):
80
+
81
+ MultiDayEvent.by_month("January") #=> returns MultiDayEvents that overlap in January,
82
+ even if they start in December and/or end in February
83
+
84
+ If you'd like to confine results to starting and ending within the given range, use the `:strict` option:
85
+
86
+ MultiDayEvent.by_month("January", strict => true) #=> returns MultiDayEvents that both start AND end in January
87
+
88
+ ## By Year (`by_year`)
89
+
90
+ To find records from the current year, simply call the method without any arguments:
91
+
92
+ Post.by_year
93
+
94
+ To find records based on a year you can pass it a two or four digit number:
95
+
96
+ Post.by_year(09)
97
+
98
+ This will return all posts in 2009, whereas:
99
+
100
+ Post.by_year(99)
101
+
102
+ will return all the posts in the year 1999.
103
+
104
+ You can also specify the full year:
105
+
106
+ Post.by_year(2009)
107
+ Post.by_year(1999)
108
+
109
+ ## By Month (`by_month`)
110
+
111
+ If you know the number of the month you want:
112
+
113
+ Post.by_month(1)
114
+
115
+ This will return all posts in the first month (January) of the current year.
116
+
117
+ If you like being verbose:
118
+
119
+ Post.by_month("January")
120
+
121
+ This will return all posts created in January of the current year.
122
+
123
+ If you want to find all posts in January of last year just do
124
+
125
+ Post.by_month(1, :year => 2007)
126
+
127
+ or
128
+
129
+ Post.by_month("January", :year => 2007)
130
+
131
+ This will perform a find using the column you've specified.
132
+
133
+ If you have a Time object you can use it to find the posts:
134
+
135
+ Post.by_month(Time.local(2012, 11, 24))
136
+
137
+ This will find all the posts in November 2012.
138
+
139
+ ## By Calendar Month (`by_calendar_month`)
140
+
141
+ 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.
142
+
143
+ Post.by_calendar_month
144
+
145
+ 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.)
146
+
147
+ ## By Fortnight (`by_fortnight`)
148
+
149
+ Fortnight numbering starts at 0. The beginning of a fortnight is Monday, 12am.
150
+
151
+ To find records from the current fortnight:
152
+
153
+ Post.by_fortnight
154
+
155
+ To find records based on a fortnight, you can pass in a number (representing the fortnight number) or a time object:
156
+
157
+ Post.by_fortnight(18)
158
+
159
+ This will return all posts in the 18th fortnight of the current year.
160
+
161
+ Post.by_fortnight(18, :year => 2012)
162
+
163
+ This will return all posts in the 18th fortnight week of 2012.
164
+
165
+ Post.by_fortnight(Time.local(2012,1,1))
166
+
167
+ This will return all posts from the first fortnight of 2012.
168
+
169
+ ## By Week (`by_week`)
170
+
171
+ Week numbering starts at 0. The beginning of a week is Monday, 12am.
172
+
173
+ To find records from the current week:
174
+
175
+ Post.by_week
176
+
177
+ To find records based on a week, you can pass in a number (representing the week number) or a time object:
178
+
179
+ Post.by_week(36)
180
+
181
+ This will return all posts in the 37th week of the current year (remember week numbering starts at 0).
182
+
183
+ Post.by_week(36, :year => 2012)
184
+
185
+ This will return all posts in the 37th week of 2012.
186
+
187
+ Post.by_week(Time.local(2012,1,1))
188
+
189
+ This will return all posts from the first week of 2012.
190
+
191
+ 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.
192
+
193
+ ## By Weekend (`by_weekend`)
194
+
195
+ If the time passed in (or the time now is a weekend) it will return posts from 12am Saturday to 11:59:59PM Sunday. If the time is a week day, it will show all posts for the coming weekend.
196
+
197
+ Post.by_weekend(Time.now)
198
+
199
+ ## By Day (`by_day` or `today`)
200
+
201
+ To find records for today:
202
+
203
+ Post.by_day
204
+ Post.today
205
+
206
+ To find records for a certain day:
207
+
208
+ Post.by_day(Time.local(2012, 1, 1))
209
+
210
+ You can also pass a string:
211
+
212
+ Post.by_day("next tuesday")
213
+
214
+ This will return all posts for the given day.
215
+
216
+ ## By Quarter (`by_quarter`)
217
+
218
+ Finds records by 3-month quarterly period of year. Quarter numbering starts at 1. The four quarters of the year begin on Jan 1, Apr 1, Jul 1, and Oct 1 respectively.
219
+
220
+ To find records from the current quarter:
221
+
222
+ Post.by_quarter
223
+
224
+ To find records based on a quarter, you can pass in a number (representing the quarter number) or a time object:
225
+
226
+ Post.by_quarter(4)
227
+
228
+ This will return all posts in the 4th quarter of the current year.
229
+
230
+ Post.by_quarter(2, :year => 2012)
231
+
232
+ This will return all posts in the 2nd quarter of 2012.
233
+
234
+ Post.by_week(Time.local(2012,1,1))
235
+
236
+ This will return all posts from the first quarter of 2012.
237
+
238
+ ## Tomorrow (`tomorrow`)
239
+
240
+ *This method has been shown to be shifty when passed a `Date` object, it is recommended that you pass it an `ActiveSupport::TimeWithZone` object instead.*
241
+
242
+ To find all posts from the day after the current date:
243
+
244
+ Post.tomorrow
245
+
246
+ To find all posts after a given Date or Time object:
247
+
248
+ Post.tomorrow(Date.today + 2)
249
+ Post.tomorrow(Time.now + 5.days)
250
+
251
+ You can also pass a string:
252
+
253
+ Post.tomorrow("next tuesday")
254
+
255
+ ## Yesterday (`yesterday`)
256
+
257
+ *This method has been shown to be shifty when passed a `Date` object, it is recommended that you pass it an `ActiveSupport::TimeWithZone` object instead.*
258
+
259
+ To find all posts from the day before the current date:
260
+
261
+ Post.yesterday
262
+
263
+ To find all posts before a given Date or Time object:
264
+
265
+ Post.yesterday(Date.today + 2)
266
+ Post.yesterday(Time.now + 5.days)
267
+
268
+ You can also pass a string:
269
+
270
+ Post.yesterday("next tuesday")
271
+
272
+ ## Before (`before`)
273
+
274
+ To find all posts before the current time:
275
+
276
+ Post.before
277
+
278
+ To find all posts before certain time or date:
279
+
280
+ Post.before(Date.today + 2)
281
+ Post.before(Time.now + 5.days)
282
+
283
+ You can also pass a string:
284
+
285
+ Post.before("next tuesday")
286
+
287
+ For Time-Range type objects, only the start time is considered for `before`.
288
+
289
+ ## After (`after`)
290
+
291
+ To find all posts after the current time:
292
+
293
+ Post.after
294
+
295
+ To find all posts after certain time or date:
296
+
297
+ Post.after(Date.today + 2)
298
+ Post.after(Time.now + 5.days)
299
+
300
+ You can also pass a string:
301
+
302
+ Post.after("next tuesday")
303
+
304
+ For Time-Range type objects, only the start time is considered for `after`.
305
+
306
+ ## Between (`between_times`)
307
+
308
+ To find records between two times:
309
+
310
+ Post.between_times(time1, time2)
311
+
312
+ Also works with dates:
313
+
314
+ Post.between_times(date1, date2)
315
+
316
+ ActiveRecord only: `between` is an alias for `between_times`:
317
+
318
+ Post.between(time1, time2) #=> results identical to between_times above
319
+
320
+ ## Previous (`previous`)
321
+
322
+ To find the record prior to this one call `previous` on any model instance:
323
+
324
+ Post.last.previous
325
+
326
+ You can specify a field also:
327
+
328
+ Post.last.previous("published_at")
329
+
330
+ For Time-Range type objects, only the start time is considered for `previous`.
331
+
332
+ ## Next (`next`)
333
+
334
+ To find the record after this one call `next` on any model instance:
335
+
336
+ Post.last.next
337
+
338
+ You can specify a field also:
339
+
340
+ Post.last.next("published_at")
341
+
342
+ For Time-Range type objects, only the start time is considered for `next`.
343
+
344
+ ## Offset option
345
+
346
+ All ByStar finders support an `:offset` option which offsets the time period for which the query is performed.
347
+ This is useful in cases where the daily cycle occurs at a time other than midnight.
348
+
349
+ Post.by_day('2014-03-05', offset: 9.hours)
350
+
351
+ ## Not using created_at? No worries!
352
+
353
+ If your database uses something other than `created_at` for storing a timestamp, you can specify the field option like this:
354
+
355
+ Post.by_month("January", :field => :something_else)
356
+
357
+ All methods support this extra option.
358
+
359
+ Or if you're doing it all the time on your model, then it's best to use `by_star_field` at the top of your model:
360
+
361
+ class Post < ActiveRecord::Base
362
+ by_star_field :something_else
363
+ end
364
+
365
+ ## Chronic Support
366
+
367
+ If [Chronic](https://github.com/mojombo/chronic) gem is present, it will be used to parse natural-language date/time
368
+ strings in all ByStar finder methods. Otherwise, the Ruby `Time.parse` kernel method will be used as a fallback.
369
+
370
+ As of ByStar 2.2.0, you must explicitly include `gem chronic` into your Gemfile in order to use Chronic.
371
+
372
+ ## Mongoid
373
+
374
+ Mongoid is only tested/supported on version 3.0+
375
+
376
+ ## Testing
377
+
378
+ Specify a database by supplying a `DB` environmental variable:
379
+
380
+ `bundle exec rake spec DB=sqlite`
381
+
382
+ You can also take an ORM-specific test task for a ride:
383
+
384
+ `bundle exec rake spec:active_record`
385
+
386
+
387
+ Have an Active Record or Mongoid version in mind? Set the environment variables
388
+ `ACTIVE_RECORD_VERSION` and `MONGOID_VERSION` to a version of your choice. A
389
+ version number provided will translate to `~> VERSION`, and the string `master`
390
+ will grab the latest from Github.
391
+
392
+ ```bash
393
+ # Update your bundle appropriately...
394
+ ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master bundle update
395
+
396
+ # ...then run the specs
397
+ ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master bundle exec rpsec spec
398
+ ```
399
+
400
+ ## Collaborators
401
+
402
+ Thanks to Thomas Sinclair for the original bump for implementing it. I would like to thank #rubyonrails for their support and the following people:
403
+
404
+ * Mislav Marohnic
405
+ * August Lilleas (leethal)
406
+ * gte351s
407
+ * Sam Elliott (lenary)
408
+ * The people who created [Chronic](https://github.com/mojombo/chronic) gem
409
+ * Erik Fonselius
410
+ * Johnny Shields (johnnyshields)
411
+
412
+ ## Suggestions?
413
+
414
+ If you have suggestions, please contact me at radarlistener@gmail.com