by_star 2.2.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +5 -5
  3. data/.travis.yml +61 -35
  4. data/CHANGELOG.md +44 -35
  5. data/Gemfile +18 -25
  6. data/MIT-LICENSE +20 -20
  7. data/README.md +577 -540
  8. data/Rakefile +18 -18
  9. data/UPGRADING +6 -12
  10. data/by_star.gemspec +34 -32
  11. data/cleaner.rb +24 -24
  12. data/lib/by_star.rb +17 -16
  13. data/lib/by_star/base.rb +68 -70
  14. data/lib/by_star/between.rb +156 -120
  15. data/lib/by_star/directional.rb +37 -33
  16. data/lib/by_star/kernel/date.rb +50 -19
  17. data/lib/by_star/kernel/time.rb +41 -41
  18. data/lib/by_star/normalization.rb +127 -118
  19. data/lib/by_star/orm/active_record/by_star.rb +61 -69
  20. data/lib/by_star/orm/mongoid/by_star.rb +76 -73
  21. data/lib/by_star/orm/mongoid/reorder.rb +23 -0
  22. data/lib/by_star/version.rb +3 -3
  23. data/spec/database.yml +15 -15
  24. data/spec/fixtures/active_record/models.rb +12 -10
  25. data/spec/fixtures/active_record/schema.rb +19 -19
  26. data/spec/fixtures/mongoid/models.rb +31 -29
  27. data/spec/fixtures/shared/seeds.rb +26 -26
  28. data/spec/gemfiles/Gemfile.master +6 -0
  29. data/spec/gemfiles/Gemfile.rails40 +7 -0
  30. data/spec/gemfiles/Gemfile.rails41 +7 -0
  31. data/spec/gemfiles/Gemfile.rails42 +7 -0
  32. data/spec/gemfiles/Gemfile.rails50 +10 -0
  33. data/spec/gemfiles/Gemfile.rails51 +10 -0
  34. data/spec/integration/active_record/active_record_spec.rb +38 -53
  35. data/spec/integration/mongoid/mongoid_spec.rb +37 -46
  36. data/spec/integration/shared/between_times.rb +82 -0
  37. data/spec/integration/shared/by_calendar_month.rb +55 -55
  38. data/spec/integration/shared/by_cweek.rb +54 -0
  39. data/spec/integration/shared/by_day.rb +96 -108
  40. data/spec/integration/shared/by_direction.rb +172 -153
  41. data/spec/integration/shared/by_fortnight.rb +48 -48
  42. data/spec/integration/shared/by_month.rb +50 -50
  43. data/spec/integration/shared/by_quarter.rb +49 -49
  44. data/spec/integration/shared/by_week.rb +54 -54
  45. data/spec/integration/shared/by_weekend.rb +49 -49
  46. data/spec/integration/shared/by_year.rb +48 -48
  47. data/spec/integration/shared/offset_parameter.rb +32 -31
  48. data/spec/integration/shared/order_parameter.rb +36 -0
  49. data/spec/integration/shared/relative.rb +174 -174
  50. data/spec/integration/shared/scope_parameter.rb +73 -72
  51. data/spec/spec_helper.rb +29 -29
  52. data/spec/unit/kernel_date_spec.rb +113 -60
  53. data/spec/unit/kernel_time_spec.rb +57 -57
  54. data/spec/unit/normalization_spec.rb +305 -255
  55. metadata +61 -62
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MWNiZTk1NWIxMjM1ZTY5ZDk1NWMzZjY5MWQ0ODM1NTU2MGU3YzRmZA==
5
- data.tar.gz: !binary |-
6
- ZGI4N2RhZmViNWU3NzdjNTc5M2ZjYmU2ZDZlYTA1MzU0YjZmYzE4ZQ==
2
+ SHA256:
3
+ metadata.gz: b215af1453a6bb5552109578699e5bc4e5e18aa4df583461b3eb9544dfba72e7
4
+ data.tar.gz: 43918eb7759cd1539fe52f3c9d33f087029e302dc25d28842b73485cc446ec67
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZDYyMDZmNTFmYWYzMDg3OWNjZTU1YzNmMmRmNDYyNWRmOGYxNjJjOWE1ZTk5
10
- OWExODkxZDA2ZGNjMDBlNDUwOTA0ZDZkMDMzMTE5MTMzYWYxMjkzYzE0NjFk
11
- NjBhOThhMWMwNDMzYWU1NmYwOTlkMTI4ZDExZGU2YmRiOTUyY2U=
12
- data.tar.gz: !binary |-
13
- ZTZiYzg5YWFmNzNkNmI2OTg4NTcwN2RkMDU3YjgwNDAyNTg0NzZmZTk5ZjNl
14
- ZDIyYzM0YzgwZWM0Y2NiMzQzYTA1YjQ2ODliMzQ5NTNjZDhlZjAwYjJjOTEy
15
- Y2QxYzY2NDVjMzUyZmVjYzczODNkMzMzM2E2MDM0ZDZiNzIyOGI=
6
+ metadata.gz: f15335c52f3dea9f54dfbf054d8b1e532535cc7cd1c9616bd7b5bf1d1a4274fb0df3d4c2619025ab1f6db975b46a93a74f77458e3533fa3867c0aaaa39a48b6a
7
+ data.tar.gz: eba9a69f7a83a0b8c65e4c1bee16451f6f4beeec1eb65d836e8b22841bfa70e02b4136b8f495577b91e023ed5f709221547ea9cc067d816a66c28e3f6ded0e27
data/.gitignore CHANGED
@@ -1,5 +1,5 @@
1
- tmp
2
- spec/fixtures/database.yml
3
- pkg
4
- by_star.sqlite3
5
- Gemfile.lock
1
+ tmp
2
+ spec/fixtures/database.yml
3
+ pkg
4
+ by_star.sqlite3
5
+ Gemfile.lock
@@ -1,35 +1,61 @@
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
1
+ before_install:
2
+ - gem update --system
3
+ - gem update bundler
4
+
5
+ before_script:
6
+ - "mysql -e 'create database by_star_test;'"
7
+ - "psql -c 'create database by_star_test;' -U postgres"
8
+
9
+ env:
10
+ - DB=sqlite
11
+ - DB=mysql
12
+ - DB=postgres
13
+ - DB=mongodb
14
+
15
+ gemfile:
16
+ - spec/gemfiles/Gemfile.rails40
17
+ - spec/gemfiles/Gemfile.rails41
18
+ - spec/gemfiles/Gemfile.rails42
19
+ - spec/gemfiles/Gemfile.rails50
20
+ - spec/gemfiles/Gemfile.rails51
21
+ - spec/gemfiles/Gemfile.master
22
+
23
+ notifications:
24
+ email:
25
+ - radarlistener@gmail.com
26
+
27
+ branches:
28
+ only:
29
+ - master
30
+
31
+ rvm:
32
+ - 2.0.0
33
+ - 2.1.9
34
+ - 2.2.5
35
+ - 2.3.1
36
+ - 2.4.2
37
+ - 2.5.0
38
+
39
+ matrix:
40
+ exclude:
41
+ - rvm: 2.0.0
42
+ gemfile: "spec/gemfiles/Gemfile.rails50"
43
+ - rvm: 2.0.0
44
+ gemfile: "spec/gemfiles/Gemfile.rails51"
45
+ - rvm: 2.1.9
46
+ gemfile: "spec/gemfiles/Gemfile.rails50"
47
+ - rvm: 2.1.9
48
+ gemfile: "spec/gemfiles/Gemfile.rails51"
49
+ - rvm: 2.4.2
50
+ gemfile: "spec/gemfiles/Gemfile.rails40"
51
+ - rvm: 2.5.0
52
+ gemfile: "spec/gemfiles/Gemfile.rails40"
53
+ - rvm: 2.4.2
54
+ gemfile: "spec/gemfiles/Gemfile.rails41"
55
+ - rvm: 2.5.0
56
+ gemfile: "spec/gemfiles/Gemfile.rails41"
57
+ allow_failures:
58
+ - gemfile: spec/gemfiles/Gemfile.master
59
+
60
+
61
+ services: mongodb
@@ -1,35 +1,44 @@
1
- # CHANGELOG
2
-
3
- ## v2.2.1 - 2014-04-21
4
-
5
- * Allow `previous` and `next` to take the current record in their scope - @pnomolos / @johnnyshields
6
- * Alias `Date#in_time_zone` to `#to_time_in_current_zone` if not already defined (e.g. for Rails <= 3) - @jcypret / @johnnyshields
7
- * Add `oldest` and `newest` methods
8
-
9
- ## v2.2.0 - 2014-04-01
10
-
11
- * Add `:scope` parameter support on all finders - @pnomolos / @johnnyshields
12
- * Feature: Add `past_*` and `next_*` finders - @davegudge
13
- * Bug Fix: `:field`, `:start_field`, and `:end_field` options were being ignored on finder - @johnnyshields / @gamov
14
- * Bug Fix: `by_star_field` should accept options without start/end_time args - @johnnyshields
15
- * Improve readme documentation - @johnnyshields
16
-
17
- ## v2.2.0.rc1 - 2014-01-14
18
-
19
- * Begin tracking CHANGELOG
20
- * Drop official support for Ruby <= 1.9.2
21
- * Add Ruby 2.1.0, Rubinius, and JRuby to Travis
22
- * Decouple gem from ActiveRecord, and put ActiveRecord and Mongoid specific methods in ORM modules.
23
- * Consolidate all normalization/parsing functions into new Normalization module
24
- * Remove meta-programming methods, e.g. `send("by_week_#{time_klass}")`
25
- * Support matching timespan-type objects with distinct start and end times (previously only point-in-time matching was supported)
26
- * Make Chronic gem optional; use it only if user has included it externally
27
- * `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.
28
- * `by_week` and `by_calendar_month` now supports optional `:start_day` option (:monday, :tuesday, etc)
29
- * Separate `by_calendar_month` into it's own class
30
- * Rename `between` method to `between_times` internally, as Mongoid already defines `between`. ActiveRecord has an alias of `between` so interface stays consistent.
31
- * 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)
32
- * `by_weekend` can now take a fixnum (parsing logic is same as by_week)
33
- * Two-digit year now considers 70 to be 1970, and 69 to be 2069 (was previously 40 -> 1940)
34
- * Add Time kernel extensions for fortnight and calendar_month
35
- * Add Johnny Shields as a gem co-author
1
+ # CHANGELOG
2
+
3
+ ## v3.0.0
4
+
5
+ * Upgrade Travis for broader coverage of Ruby, ActiveRecord, and Mongoid versions - @johnnyshields
6
+ * Removed support for Ruby < 2.0 and Rails < 4.0. They are over 5 years old, and so it's time to upgrade. - @radar
7
+ * Removed references to deprecated Fixnum constant - @rgioia - #78
8
+ * Mongoid `newest`, `oldest`, `previous`, and `next` now use `reorder` to ignore any default scope, consistent with ActiveRecord - @johnnyshields
9
+ * Mongoid 3.x: Add support for `Criteria#reorder` method from version 4+ - @johnnyshields
10
+ * Upgrade Rspec tests to version 3.1 - @nhocki
11
+
12
+ ## v2.2.1 - 2014-04-21
13
+
14
+ * Allow `previous` and `next` to take the current record in their scope - @pnomolos / @johnnyshields
15
+ * Alias `Date#in_time_zone` to `#to_time_in_current_zone` if not already defined (e.g. for Rails <= 3) - @jcypret / @johnnyshields
16
+ * Add `oldest` and `newest` methods
17
+
18
+ ## v2.2.0 - 2014-04-01
19
+
20
+ * Add `:scope` parameter support on all finders - @pnomolos / @johnnyshields
21
+ * Feature: Add `past_*` and `next_*` finders - @davegudge
22
+ * Bug Fix: `:field`, `:start_field`, and `:end_field` options were being ignored on finder - @johnnyshields / @gamov
23
+ * Bug Fix: `by_star_field` should accept options without start/end_time args - @johnnyshields
24
+ * Improve readme documentation - @johnnyshields
25
+
26
+ ## v2.2.0.rc1 - 2014-01-14
27
+
28
+ * Begin tracking CHANGELOG
29
+ * Drop official support for Ruby <= 1.9.2
30
+ * Add Ruby 2.1.0, Rubinius, and JRuby to Travis
31
+ * Decouple gem from ActiveRecord, and put ActiveRecord and Mongoid specific methods in ORM modules.
32
+ * Consolidate all normalization/parsing functions into new Normalization module
33
+ * Remove meta-programming methods, e.g. `send("by_week_#{time_klass}")`
34
+ * Support matching timespan-type objects with distinct start and end times (previously only point-in-time matching was supported)
35
+ * Make Chronic gem optional; use it only if user has included it externally
36
+ * `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.
37
+ * `by_week` and `by_calendar_month` now supports optional `:start_day` option (:monday, :tuesday, etc)
38
+ * Separate `by_calendar_month` into it's own class
39
+ * Rename `between` method to `between_times` internally, as Mongoid already defines `between`. ActiveRecord has an alias of `between` so interface stays consistent.
40
+ * 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)
41
+ * `by_weekend` can now take a fixnum (parsing logic is same as by_week)
42
+ * Two-digit year now considers 70 to be 1970, and 69 to be 2069 (was previously 40 -> 1940)
43
+ * Add Time kernel extensions for fortnight and calendar_month
44
+ * Add Johnny Shields as a gem co-author
data/Gemfile CHANGED
@@ -1,25 +1,18 @@
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
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ ar_version = ENV['ACTIVE_RECORD_VERSION']
6
+ ar_version = case ar_version
7
+ when 'master' then {github: 'rails'}
8
+ when String then "~> #{ar_version}"
9
+ end
10
+
11
+ mo_version = ENV['MONGOID_VERSION']
12
+ mo_version = case mo_version
13
+ when 'master' then {github: 'mongoid'}
14
+ when String then "~> #{mo_version}"
15
+ end
16
+
17
+ gem 'activerecord', ar_version if ar_version
18
+ gem 'mongoid', mo_version if mo_version
@@ -1,20 +1,20 @@
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
+ 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.
data/README.md CHANGED
@@ -1,540 +1,577 @@
1
- # ByStar
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
- ByStar (by_*) allows you easily and reliably query ActiveRecord and Mongoid objects based on time.
7
-
8
- ### Examples
9
-
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 in 2013
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
- ```
18
-
19
- ## Installation
20
-
21
- Install this gem by adding this to your Gemfile:
22
-
23
- ```ruby
24
- gem 'by_star', :git => "git://github.com/radar/by_star"
25
- ```
26
-
27
- Then run `bundle install`
28
-
29
- If you are using ActiveRecord, you're done!
30
-
31
- Mongoid users, please include the Mongoid::ByStar module for each model you wish to use the functionality.
32
- This is the convention among Mongoid plugins.
33
-
34
- ```ruby
35
- class MyModel
36
- include Mongoid::Document
37
- include Mongoid::ByStar
38
- ```
39
-
40
- ## Finder Methods
41
-
42
- ### Base Scopes
43
-
44
- ByStar adds the following finder scopes (class methods) to your model to query time ranges.
45
- These accept a `Date`, `Time`, or `DateTime` object as an argument, which defaults to `Time.zone.now` if not specified:
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
50
-
51
- ### Time Range Scopes
52
-
53
- ByStar adds additional shortcut scopes based on commonly used time ranges.
54
- See sections below for detailed argument usage of each:
55
-
56
- * `by_day`
57
- * `by_week`
58
- * `by_weekend` 60-hour period from 15:00 Friday to 03:00 Monday
59
- * `by_fortnight` A two-week period, with the first fortnight of the year beginning on 1st January
60
- * `by_month`
61
- * `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
62
- * `by_quarter` 3-month intervals of the year
63
- * `by_year`
64
-
65
- ### Relative Scopes
66
-
67
- ByStar also adds scopes which are relative to the current time.
68
- Note the `past_*` and `next_*` methods represent a time distance from current time (`Time.zone.now`),
69
- and do not strictly end/begin evenly on a calendar week/month/year (unlike `by_*` methods which do.)
70
-
71
- * `today` Finds all occurrences on today's date
72
- * `yesterday` Finds all occurrences on yesterday's date
73
- * `tomorrow` Finds all occurrences on tomorrow's date
74
- * `past_day` Prior 24-hour period from current time
75
- * `past_week` Prior 7-day period from current time
76
- * `past_fortnight` Prior 14-day period from current time
77
- * `past_month` Prior 30-day period from current time
78
- * `past_year` Prior 365-day period from current time
79
- * `next_day` Subsequent 24-hour period from current time
80
- * `next_week` Subsequent 7-day period from current time
81
- * `next_fortnight` Subsequent 14-day period from current time
82
- * `next_month` Subsequent 30-day period from current time
83
- * `next_year` Subsequent 365-day period from current time
84
-
85
- ### Superlative Finders
86
-
87
- Find the oldest or newest records. Returns an object instance (not a relation):
88
-
89
- * `newest`
90
- * `oldest`
91
-
92
- ### Instance Methods
93
-
94
- In addition, ByStar adds instance methods to return the next / previous record in the timewise sequence.
95
- Returns an object instance (not a relation):
96
-
97
- * `object.next`
98
- * `object.previous`
99
-
100
- ### Kernel Extensions
101
-
102
- ByStar extends the kernel `Date`, `Time`, and `DateTime` objects with the following instance methods,
103
- which mirror the ActiveSupport methods `beginning_of_day`, `end_of_week`, etc:
104
-
105
- * `beginning_of_weekend`
106
- * `end_of_weekend`
107
- * `beginning_of_fortnight`
108
- * `end_of_fortnight`
109
- * `beginning_of_calendar_month`
110
- * `end_of_calendar_month`
111
-
112
- Lastly, ByStar aliases Rails 3 `Date#to_time_in_current_zone` to the Rails 4 syntax `#in_time_zone`, if it has not already been defined.
113
-
114
- ## Usage
115
-
116
- ### Setting the Query Field
117
-
118
- By default, ByStar assumes you will use the `created_at` field to query objects by time.
119
- You may specify an alternate field on all query methods as follows:
120
-
121
- ```ruby
122
- Post.by_month("January", field: :updated_at)
123
- ```
124
-
125
- Alternatively, you may set a default in your model using the `by_star_field` macro:
126
-
127
- ```ruby
128
- class Post < ActiveRecord::Base
129
- by_star_field :updated_at
130
- end
131
- ```
132
-
133
- ### Scoping the Find
134
-
135
- All ByStar methods (except `oldest`, `newest`, `previous`, `next`) return `ActiveRecord::Relation` and/or
136
- `Mongoid::Criteria` objects, which can be daisy-chained with other scopes/finder methods:
137
-
138
- ```ruby
139
- Post.by_month.your_scope
140
- Post.by_month(1).include(:tags).where("tags.name" => "ruby")
141
- ```
142
-
143
- Want to count records? Simple:
144
-
145
- ```ruby
146
- Post.by_month.count
147
- ```
148
-
149
- ### :scope Option
150
-
151
- You may pass a `:scope` option as a Relation or Proc to all ByStar methods like so:
152
-
153
- ```ruby
154
- @post.next(scope: Post.where(category: @post.category))
155
- @post.next(scope: ->{ where(category: 'blog') })
156
- ```
157
-
158
- This is particularly useful for `oldest`, `newest`, `previous`, `next` which return a model instance rather than
159
- a Relation and hence cannot be daisy-chained with other scopes.
160
-
161
- `previous` and `next` support a special feature that the `:scope` option may take the subject record as an argument:
162
-
163
- ```ruby
164
- @post.next(scope: ->(record){ where(category: record.category) })
165
- ```
166
-
167
- You may also set a default scope in the `by_star_field` macro. (It is recommended this be a Proc):
168
-
169
- ```ruby
170
- class Post < ActiveRecord::Base
171
- by_star_field scope: ->{ where(category: 'blog') }
172
- end
173
- ```
174
-
175
- ### :offset Option
176
-
177
- All ByStar finders support an `:offset` option which offsets the time period for which the query is performed.
178
- This is useful in cases where the daily cycle occurs at a time other than midnight.
179
-
180
- Post.by_day('2014-03-05', offset: 9.hours)
181
-
182
- You may also set a offset scope in the `by_star_field` macro:
183
-
184
- ```ruby
185
- class Post < ActiveRecord::Base
186
- by_star_field offset: offset: 9.hours
187
- end
188
- ```
189
-
190
- ### Time-Range Type Objects
191
-
192
- If your object has both a start and end time, you may pass both params to `by_star_field`:
193
-
194
- ```ruby
195
- by_star_field :start_time, :end_time
196
- ```
197
-
198
- By default, ByStar queries will return all objects whose range has any overlap within the desired period (permissive):
199
-
200
- ```ruby
201
- MultiDayEvent.by_month("January") #=> returns MultiDayEvents that overlap in January,
202
- even if they start in December and/or end in February
203
- ```
204
-
205
- If you'd like to confine results to starting and ending within the given range, use the `:strict` option:
206
-
207
- ```ruby
208
- MultiDayEvent.by_month("January", strict => true) #=> returns MultiDayEvents that both start AND end in January
209
- ```
210
-
211
- ### Chronic Support
212
-
213
- If [Chronic](https://github.com/mojombo/chronic) gem is present, it will be used to parse natural-language date/time
214
- strings in all ByStar finder methods. Otherwise, the Ruby `Time.parse` kernel method will be used as a fallback.
215
-
216
- As of ByStar 2.2.0, you must explicitly include `gem chronic` into your Gemfile in order to use Chronic.
217
-
218
-
219
- ## Advanced Usage
220
-
221
- ### between_times
222
-
223
- To find records between two times:
224
-
225
- ```ruby
226
- Post.between_times(time1, time2)
227
- ```
228
-
229
- Also works with dates:
230
-
231
- ```ruby
232
- Post.between_times(date1, date2)
233
- ```
234
-
235
- ActiveRecord only: `between` is an alias for `between_times`:
236
-
237
- ```ruby
238
- Post.between(time1, time2) #=> results identical to between_times above
239
- ```
240
-
241
- ### before and after
242
-
243
- To find all posts before / after the current time:
244
-
245
- ```ruby
246
- Post.before
247
- Post.after
248
- ```
249
-
250
- To find all posts before certain time or date:
251
-
252
- ```ruby
253
- Post.before(Date.today + 2)
254
- Post.after(Time.now + 5.days)
255
- ```
256
-
257
- You can also pass a string:
258
-
259
- ```ruby
260
- Post.before("next tuesday")
261
- ```
262
-
263
- For Time-Range type objects, only the start time is considered for `before` and `after`.
264
-
265
- ### previous and next
266
-
267
- To find the prior/subsequent record to a model instance, `previous`/`next` on it:
268
-
269
- ```ruby
270
- Post.last.previous
271
- Post.first.next
272
- ```
273
-
274
- You can specify a field also:
275
-
276
- ```ruby
277
- Post.last.previous(field: "published_at")
278
- Post.first.next(field: "published_at")
279
- ```
280
-
281
- For Time-Range type objects, only the start time is considered for `previous` and `next`.
282
-
283
- ### by_year
284
-
285
- To find records from the current year, simply call the method without any arguments:
286
-
287
- ```ruby
288
- Post.by_year
289
- ```
290
-
291
- To find records based on a year you can pass it a two or four digit number:
292
-
293
- ```ruby
294
- Post.by_year(09)
295
- ```
296
-
297
- This will return all posts in 2009, whereas:
298
-
299
- ```ruby
300
- Post.by_year(99)
301
- ```
302
-
303
- will return all the posts in the year 1999.
304
-
305
- You can also specify the full year:
306
-
307
- ```ruby
308
- Post.by_year(2009)
309
- Post.by_year(1999)
310
- ```
311
-
312
- ### by_month
313
-
314
- If you know the number of the month you want:
315
-
316
- ```ruby
317
- Post.by_month(1)
318
- ```
319
-
320
- This will return all posts in the first month (January) of the current year.
321
-
322
- If you like being verbose:
323
-
324
- ```ruby
325
- Post.by_month("January")
326
- ```
327
-
328
- This will return all posts created in January of the current year.
329
-
330
- If you want to find all posts in January of last year just do
331
-
332
- ```ruby
333
- Post.by_month(1, :year => 2007)
334
- ```
335
-
336
- or
337
-
338
- ```ruby
339
- Post.by_month("January", :year => 2007)
340
-
341
- This will perform a find using the column you've specified.
342
-
343
- If you have a Time object you can use it to find the posts:
344
-
345
- ```ruby
346
- Post.by_month(Time.local(2012, 11, 24))
347
- ```
348
-
349
- This will find all the posts in November 2012.
350
-
351
- ### by_calendar_month
352
-
353
- 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.
354
-
355
- ```ruby
356
- Post.by_calendar_month
357
- ```
358
-
359
- 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.)
360
-
361
- ### by_fortnight
362
-
363
- Fortnight numbering starts at 0. The beginning of a fortnight is Monday, 12am.
364
-
365
- To find records from the current fortnight:
366
-
367
- ```ruby
368
- Post.by_fortnight
369
- ```
370
-
371
- To find records based on a fortnight, you can pass in a number (representing the fortnight number) or a time object:
372
-
373
- ```ruby
374
- Post.by_fortnight(18)
375
- ```
376
-
377
- This will return all posts in the 18th fortnight of the current year.
378
-
379
- ```ruby
380
- Post.by_fortnight(18, :year => 2012)
381
- ```
382
-
383
- This will return all posts in the 18th fortnight week of 2012.
384
-
385
- ```ruby
386
- Post.by_fortnight(Time.local(2012,1,1))
387
- ```
388
-
389
- This will return all posts from the first fortnight of 2012.
390
-
391
- ### by_week
392
-
393
- Week numbering starts at 0. The beginning of a week is Monday, 12am.
394
-
395
- To find records from the current week:
396
-
397
- ```ruby
398
- Post.by_week
399
- ```
400
-
401
- To find records based on a week, you can pass in a number (representing the week number) or a time object:
402
-
403
- ```ruby
404
- Post.by_week(36)
405
- ```
406
-
407
- This will return all posts in the 37th week of the current year (remember week numbering starts at 0).
408
-
409
- ```ruby
410
- Post.by_week(36, :year => 2012)
411
- ```
412
-
413
- This will return all posts in the 37th week of 2012.
414
-
415
- ```ruby
416
- Post.by_week(Time.local(2012,1,1))
417
- ```
418
-
419
- This will return all posts from the first week of 2012.
420
-
421
- 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.
422
-
423
- ### by_weekend
424
-
425
- 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.
426
-
427
- ```ruby
428
- Post.by_weekend(Time.now)
429
- ```
430
-
431
- ### by_day and today
432
-
433
- To find records for today:
434
-
435
- ```ruby
436
- Post.by_day
437
- Post.today
438
- ```
439
-
440
- To find records for a certain day:
441
-
442
- ```ruby
443
- Post.by_day(Time.local(2012, 1, 1))
444
- ```
445
-
446
- You can also pass a string:
447
-
448
- ```ruby
449
- Post.by_day("next tuesday")
450
- ```
451
-
452
- This will return all posts for the given day.
453
-
454
- ### by_quarter
455
-
456
- 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.
457
-
458
- To find records from the current quarter:
459
-
460
- ```ruby
461
- Post.by_quarter
462
- ```
463
-
464
- To find records based on a quarter, you can pass in a number (representing the quarter number) or a time object:
465
-
466
- ```ruby
467
- Post.by_quarter(4)
468
- ```
469
-
470
- This will return all posts in the 4th quarter of the current year.
471
-
472
- ```ruby
473
- Post.by_quarter(2, :year => 2012)
474
- ```
475
-
476
- This will return all posts in the 2nd quarter of 2012.
477
-
478
- ```ruby
479
- Post.by_week(Time.local(2012,1,1))
480
- ```
481
-
482
- This will return all posts from the first quarter of 2012.
483
-
484
-
485
- ## Version Support
486
-
487
- ByStar is tested against the following versions:
488
-
489
- * Ruby 1.9.3+
490
- * Rails/ActiveRecord 3.0+
491
- * Mongoid 3.0+
492
-
493
-
494
- ## Testing
495
-
496
- ### Test Setup
497
-
498
- Specify a database by supplying a `DB` environmental variable:
499
-
500
- `bundle exec rake spec DB=sqlite`
501
-
502
- You can also take an ORM-specific test task for a ride:
503
-
504
- `bundle exec rake spec:active_record`
505
-
506
- Have an Active Record or Mongoid version in mind? Set the environment variables
507
- `ACTIVE_RECORD_VERSION` and `MONGOID_VERSION` to a version of your choice. A
508
- version number provided will translate to `~> VERSION`, and the string `master`
509
- will grab the latest from Github.
510
-
511
- ```bash
512
- # Update your bundle appropriately...
513
- ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master bundle update
514
-
515
- # ...then run the specs
516
- ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master bundle exec rpsec spec
517
- ```
518
-
519
- ### Test Implementation
520
-
521
- ByStar tests use TimeCop to lock the system `Time.now` at Jan 01, 2014, and seed
522
- objects with fixed dates according to `spec/fixtures/shared/seeds.rb`.
523
- Note that the timezone is randomized on each run to shake-out timezone related quirks.
524
-
525
-
526
- ## Collaborators
527
-
528
- ByStar is actively maintained by Ryan Biggs (radar) and Johnny Shields (johnnyshields)
529
-
530
- Thank you to the following people:
531
-
532
- * Thomas Sinclair for the original bump for implementing ByStar
533
- * [Ruby on Rails](http://rubyonrails.org/) for their support
534
- * Mislav Marohnic
535
- * August Lilleas (leethal)
536
- * gte351s
537
- * Sam Elliott (lenary)
538
- * The creators of the [Chronic](https://github.com/mojombo/chronic) gem
539
- * Erik Fonselius
540
- * Johnny Shields (johnnyshields)
1
+ # ByStar
2
+
3
+ [![Build Status](https://travis-ci.org/radar/by_star.svg)](https://travis-ci.org/radar/by_star)
4
+ [![Code Climate](https://codeclimate.com/github/radar/by_star.svg)](https://codeclimate.com/github/radar/by_star)
5
+
6
+ ByStar (by_*) allows you easily and reliably query ActiveRecord and Mongoid objects based on time.
7
+
8
+ ### Examples
9
+
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
17
+ ```
18
+
19
+ ## Installation
20
+
21
+ Install this gem by adding this to your Gemfile:
22
+
23
+ ```ruby
24
+ gem 'by_star', git: "git://github.com/radar/by_star"
25
+ ```
26
+
27
+ Then run `bundle install`
28
+
29
+ If you are using ActiveRecord, you're done!
30
+
31
+ Mongoid users, please include the Mongoid::ByStar module for each model you wish to use the functionality.
32
+ This is the convention among Mongoid plugins.
33
+
34
+ ```ruby
35
+ class MyModel
36
+ include Mongoid::Document
37
+ include Mongoid::ByStar
38
+ ```
39
+
40
+ ## Finder Methods
41
+
42
+ ### Base Scopes
43
+
44
+ ByStar adds the following finder scopes (class methods) to your model to query time ranges.
45
+ These accept a `Date`, `Time`, or `DateTime` object as an argument, which defaults to `Time.zone.now` if not specified:
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
50
+
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)`
56
+
57
+ ### Time Range Scopes
58
+
59
+ ByStar adds additional shortcut scopes based on commonly used time ranges.
60
+ See sections below for detailed argument usage of each:
61
+
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`
71
+
72
+ ### Relative Scopes
73
+
74
+ ByStar also adds scopes which are relative to the current time.
75
+ Note the `past_*` and `next_*` methods represent a time distance from current time (`Time.zone.now`),
76
+ and do not strictly end/begin evenly on a calendar week/month/year (unlike `by_*` methods which do.)
77
+
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
91
+
92
+ ### Superlative Finders
93
+
94
+ Find the oldest or newest records. Returns an object instance (not a relation):
95
+
96
+ * `newest`
97
+ * `oldest`
98
+
99
+ ### Instance Methods
100
+
101
+ In addition, ByStar adds instance methods to return the next / previous record in the timewise sequence.
102
+ Returns an object instance (not a relation):
103
+
104
+ * `object.next`
105
+ * `object.previous`
106
+
107
+ ### Kernel Extensions
108
+
109
+ ByStar extends the kernel `Date`, `Time`, and `DateTime` objects with the following instance methods,
110
+ which mirror the ActiveSupport methods `beginning_of_day`, `end_of_week`, etc:
111
+
112
+ * `beginning_of_weekend`
113
+ * `end_of_weekend`
114
+ * `beginning_of_fortnight`
115
+ * `end_of_fortnight`
116
+ * `beginning_of_calendar_month`
117
+ * `end_of_calendar_month`
118
+
119
+ Lastly, ByStar aliases Rails 3 `Date#to_time_in_current_zone` to the Rails 4 syntax `#in_time_zone`, if it has not already been defined.
120
+
121
+ ## Usage
122
+
123
+ ### Setting the Query Field
124
+
125
+ By default, ByStar assumes you will use the `created_at` field to query objects by time.
126
+ You may specify an alternate field on all query methods as follows:
127
+
128
+ ```ruby
129
+ Post.by_month("January", field: :updated_at)
130
+ ```
131
+
132
+ Alternatively, you may set a default in your model using the `by_star_field` macro:
133
+
134
+ ```ruby
135
+ class Post < ActiveRecord::Base
136
+ by_star_field :updated_at
137
+ end
138
+ ```
139
+
140
+ ### Scoping the Query
141
+
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:
144
+
145
+ ```ruby
146
+ Post.by_month.your_scope
147
+ Post.by_month(1).include(:tags).where("tags.name" => "ruby")
148
+ ```
149
+
150
+ Want to count records? Simple:
151
+
152
+ ```ruby
153
+ Post.by_month.count
154
+ ```
155
+
156
+ ### :scope Option
157
+
158
+ You may pass a `:scope` option as a Relation or Proc to all ByStar methods like so:
159
+
160
+ ```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
180
+ ```
181
+
182
+ ### `:offset` Option
183
+
184
+ All ByStar finders support an `:offset` option which is applied to time period of the query condition.
185
+ This is useful in cases where the daily cycle occurs at a time other than midnight.
186
+
187
+ 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
+
189
+ Post.by_day('2014-03-05', offset: 9.hours)
190
+
191
+ You may also set a offset scope in the `by_star_field` macro:
192
+
193
+ ```ruby
194
+ class Post < ActiveRecord::Base
195
+ by_star_field offset: 9.hours
196
+ end
197
+ ```
198
+
199
+ ### Timespan Objects
200
+
201
+ If your object has both a start and end time, you may pass both params to `by_star_field`:
202
+
203
+ ```ruby
204
+ by_star_field :start_time, :end_time
205
+ ```
206
+
207
+ By default, ByStar queries will return all objects whose range has any overlap within the desired period (permissive):
208
+
209
+ ```ruby
210
+ MultiDayEvent.by_month("January") #=> returns MultiDayEvents that overlap in January,
211
+ even if they start in December and/or end in February
212
+ ```
213
+
214
+ ### Timespan Objects: `:strict` Option
215
+
216
+ If you'd like to confine results to only those both starting and ending within the given range, use the `:strict` option:
217
+
218
+ ```ruby
219
+ MultiDayEvent.by_month("January", :strict => true) #=> returns MultiDayEvents that both start AND end in January
220
+ ```
221
+
222
+ ### Timespan Objects: Database Indexing and `:index_start` Option
223
+
224
+ 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
+
226
+ Database indexes require querying a range query on a single field, i.e. `start_time >= X and start_time <= Y`.
227
+ If we use a single-sided query, the database will iterate through all items either from the beginning or until the end of time.
228
+ This poses a challenge for timespan-type objects which have two fields, i.e. `start_time` and `end_time`.
229
+ There are two cases to consider:
230
+
231
+ 1) Timespan with `:strict` option, e.g. "start_time >= X and end_time <= Y".
232
+
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.
234
+
235
+ 2) Timespan without `:strict` option, e.g. "start_time < Y and end_time > X".
236
+
237
+ This is not yet supported but will be soon.
238
+
239
+
240
+ ### Chronic Support
241
+
242
+ If [Chronic](https://github.com/mojombo/chronic) gem is present, it will be used to parse natural-language date/time
243
+ strings in all ByStar finder methods. Otherwise, the Ruby `Time.parse` kernel method will be used as a fallback.
244
+
245
+ As of ByStar 2.2.0, you must explicitly include `gem 'chronic'` into your Gemfile in order to use Chronic.
246
+
247
+
248
+ ## Advanced Usage
249
+
250
+ ### between_times
251
+
252
+ To find records between two times:
253
+
254
+ ```ruby
255
+ Post.between_times(time1, time2)
256
+ ```
257
+
258
+ You use a Range like so:
259
+
260
+ ```ruby
261
+ Post.between_times(time1..time2)
262
+ ```
263
+
264
+ Also works with dates - WARNING: there are currently some caveats see [Issue #49](https://github.com/radar/by_star/issues/49):
265
+
266
+ ```ruby
267
+ Post.between_times(date1, date2)
268
+ ```
269
+
270
+ ### before and after
271
+
272
+ To find all posts before / after the current time:
273
+
274
+ ```ruby
275
+ Post.before
276
+ Post.after
277
+ ```
278
+
279
+ To find all posts before certain time or date:
280
+
281
+ ```ruby
282
+ Post.before(Date.today + 2)
283
+ Post.after(Time.now + 5.days)
284
+ ```
285
+
286
+ You can also pass a string:
287
+
288
+ ```ruby
289
+ Post.before("next tuesday")
290
+ ```
291
+
292
+ For Time-Range type objects, only the start time is considered for `before` and `after`.
293
+
294
+ ### previous and next
295
+
296
+ To find the prior/subsequent record to a model instance, `previous`/`next` on it:
297
+
298
+ ```ruby
299
+ Post.last.previous
300
+ Post.first.next
301
+ ```
302
+
303
+ You can specify a field also:
304
+
305
+ ```ruby
306
+ Post.last.previous(field: "published_at")
307
+ Post.first.next(field: "published_at")
308
+ ```
309
+
310
+ For Time-Range type objects, only the start time is considered for `previous` and `next`.
311
+
312
+ ### by_year
313
+
314
+ To find records from the current year, simply call the method without any arguments:
315
+
316
+ ```ruby
317
+ Post.by_year
318
+ ```
319
+
320
+ To find records based on a year you can pass it a two or four digit number:
321
+
322
+ ```ruby
323
+ Post.by_year(09)
324
+ ```
325
+
326
+ This will return all posts in 2009, whereas:
327
+
328
+ ```ruby
329
+ Post.by_year(99)
330
+ ```
331
+
332
+ will return all the posts in the year 1999.
333
+
334
+ You can also specify the full year:
335
+
336
+ ```ruby
337
+ Post.by_year(2009)
338
+ Post.by_year(1999)
339
+ ```
340
+
341
+ ### by_month
342
+
343
+ If you know the number of the month you want:
344
+
345
+ ```ruby
346
+ Post.by_month(1)
347
+ ```
348
+
349
+ This will return all posts in the first month (January) of the current year.
350
+
351
+ If you like being verbose:
352
+
353
+ ```ruby
354
+ Post.by_month("January")
355
+ ```
356
+
357
+ This will return all posts created in January of the current year.
358
+
359
+ If you want to find all posts in January of last year just do
360
+
361
+ ```ruby
362
+ Post.by_month(1, year: 2007)
363
+ ```
364
+
365
+ or
366
+
367
+ ```ruby
368
+ Post.by_month("January", year: 2007)
369
+ ```
370
+
371
+ This will perform a find using the column you've specified.
372
+
373
+ If you have a Time object you can use it to find the posts:
374
+
375
+ ```ruby
376
+ Post.by_month(Time.local(2012, 11, 24))
377
+ ```
378
+
379
+ This will find all the posts in November 2012.
380
+
381
+ ### by_calendar_month
382
+
383
+ 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
+
385
+ ```ruby
386
+ Post.by_calendar_month
387
+ ```
388
+
389
+ 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.)
390
+
391
+ ### by_fortnight
392
+
393
+ Fortnight numbering starts at 0. The beginning of a fortnight is Monday, 12am.
394
+
395
+ To find records from the current fortnight:
396
+
397
+ ```ruby
398
+ Post.by_fortnight
399
+ ```
400
+
401
+ To find records based on a fortnight, you can pass in a number (representing the fortnight number) or a time object:
402
+
403
+ ```ruby
404
+ Post.by_fortnight(18)
405
+ ```
406
+
407
+ This will return all posts in the 18th fortnight of the current year.
408
+
409
+ ```ruby
410
+ Post.by_fortnight(18, year: 2012)
411
+ ```
412
+
413
+ This will return all posts in the 18th fortnight week of 2012.
414
+
415
+ ```ruby
416
+ Post.by_fortnight(Time.local(2012,1,1))
417
+ ```
418
+
419
+ This will return all posts from the first fortnight of 2012.
420
+
421
+ ### by_week and by_cweek
422
+
423
+ Week numbering starts at 0, and cweek numbering starts at 1 (same as `Date#cweek`). The beginning of a week is as defined in `ActiveSupport#beginning_of_week`, which can be configured.
424
+
425
+ To find records from the current week:
426
+
427
+ ```ruby
428
+ Post.by_week
429
+ Post.by_cweek # same result
430
+ ```
431
+
432
+ This will return all posts in the 37th week of the current year (remember week numbering starts at 0):
433
+
434
+ ```ruby
435
+ Post.by_week(36)
436
+ Post.by_cweek(37) # same result
437
+ ```
438
+
439
+ This will return all posts in the 37th week of 2012:
440
+
441
+ ```ruby
442
+ Post.by_week(36, year: 2012)
443
+ Post.by_cweek(37, year: 2012) # same result
444
+ ```
445
+
446
+ This will return all posts in the week which contains Jan 1, 2012:
447
+
448
+ ```ruby
449
+ Post.by_week(Time.local(2012,1,1))
450
+ Post.by_cweek(Time.local(2012,1,1)) # same result
451
+ ```
452
+
453
+ 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.
454
+
455
+ ### by_weekend
456
+
457
+ 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
+
459
+ ```ruby
460
+ Post.by_weekend(Time.now)
461
+ ```
462
+
463
+ ### by_day and today
464
+
465
+ To find records for today:
466
+
467
+ ```ruby
468
+ Post.by_day
469
+ Post.today
470
+ ```
471
+
472
+ To find records for a certain day:
473
+
474
+ ```ruby
475
+ Post.by_day(Time.local(2012, 1, 1))
476
+ ```
477
+
478
+ You can also pass a string:
479
+
480
+ ```ruby
481
+ Post.by_day("next tuesday")
482
+ ```
483
+
484
+ This will return all posts for the given day.
485
+
486
+ ### by_quarter
487
+
488
+ 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.
489
+
490
+ To find records from the current quarter:
491
+
492
+ ```ruby
493
+ Post.by_quarter
494
+ ```
495
+
496
+ To find records based on a quarter, you can pass in a number (representing the quarter number) or a time object:
497
+
498
+ ```ruby
499
+ Post.by_quarter(4)
500
+ ```
501
+
502
+ This will return all posts in the 4th quarter of the current year.
503
+
504
+ ```ruby
505
+ Post.by_quarter(2, year: 2012)
506
+ ```
507
+
508
+ This will return all posts in the 2nd quarter of 2012.
509
+
510
+ ```ruby
511
+ Post.by_week(Time.local(2012,1,1))
512
+ ```
513
+
514
+ This will return all posts from the first quarter of 2012.
515
+
516
+
517
+ ## Version Support
518
+
519
+ ByStar is tested against the following versions:
520
+
521
+ * Ruby 1.9.3+
522
+ * Rails/ActiveRecord 3.0+
523
+ * Mongoid 3.0+
524
+
525
+ Note that ByStar automatically adds the following version compatibility shims:
526
+
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+
529
+
530
+
531
+ ## Testing
532
+
533
+ ### Test Setup
534
+
535
+ Specify a database by supplying a `DB` environmental variable:
536
+
537
+ `bundle exec rake spec DB=sqlite`
538
+
539
+ You can also take an ORM-specific test task for a ride:
540
+
541
+ `bundle exec rake spec:active_record`
542
+
543
+ Have an Active Record or Mongoid version in mind? Set the environment variables
544
+ `ACTIVE_RECORD_VERSION` and `MONGOID_VERSION` to a version of your choice. A
545
+ version number provided will translate to `~> VERSION`, and the string `master`
546
+ will grab the latest from Github.
547
+
548
+ ```bash
549
+ # Update your bundle appropriately...
550
+ ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master bundle update
551
+
552
+ # ...then run the specs
553
+ ACTIVE_RECORD_VERSION=4.0.0 MONGOID_VERSION=master bundle exec rpsec spec
554
+ ```
555
+
556
+ ### Test Implementation
557
+
558
+ ByStar tests use TimeCop to lock the system `Time.now` at Jan 01, 2014, and seed
559
+ objects with fixed dates according to `spec/fixtures/shared/seeds.rb`.
560
+ Note that the timezone is randomized on each run to shake-out timezone related quirks.
561
+
562
+
563
+ ## Collaborators
564
+
565
+ ByStar is actively maintained by Ryan Bigg (radar) and Johnny Shields (johnnyshields)
566
+
567
+ Thank you to the following people:
568
+
569
+ * Thomas Sinclair for the original bump for implementing ByStar
570
+ * [Ruby on Rails](http://rubyonrails.org/) for their support
571
+ * Mislav Marohnic
572
+ * August Lilleas (leethal)
573
+ * gte351s
574
+ * Sam Elliott (lenary)
575
+ * The creators of the [Chronic](https://github.com/mojombo/chronic) gem
576
+ * Erik Fonselius
577
+ * Johnny Shields (johnnyshields)