include_date_scopes 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -51
- data/include_date_scopes.gemspec +1 -1
- data/lib/include_date_scopes/date_scopes.rb +14 -203
- data/lib/include_date_scopes/define_common_scopes.rb +45 -0
- data/lib/include_date_scopes/define_date_scopes.rb +31 -0
- data/lib/include_date_scopes/define_timestamp_scopes.rb +92 -0
- data/lib/include_date_scopes/version.rb +1 -1
- data/spec/lib/date_scopes_spec.rb +14 -0
- data/spec/support/date_scope_examples.rb +197 -131
- data/spec/support/timestamp_scope_examples.rb +250 -321
- metadata +6 -3
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
module IncludeDateScopes
|
3
|
+
module DefineTimestampScopes
|
4
|
+
|
5
|
+
def define_timestamp_scopes_for(column_name, prepend_name = false)
|
6
|
+
prefix = prepend_name ? "#{column_name}_" : ""
|
7
|
+
t = self.arel_table
|
8
|
+
|
9
|
+
define_singleton_method :"#{prefix}between" do |start_date_or_time, stop_date_or_time|
|
10
|
+
start_time = (start_date_or_time.is_a?(Date) ? start_date_or_time.to_time : start_date_or_time)
|
11
|
+
stop_time = (stop_date_or_time.is_a?(Date) ? stop_date_or_time.to_time + 1.day : stop_date_or_time )
|
12
|
+
where(t[column_name].gteq(start_time).and(t[column_name].lteq stop_time))
|
13
|
+
end
|
14
|
+
|
15
|
+
define_singleton_method :"#{prefix}on_or_before_date" do |date|
|
16
|
+
where( t[column_name].lt date.to_date.tomorrow.midnight.gmtime )
|
17
|
+
end
|
18
|
+
|
19
|
+
define_singleton_method :"#{prefix}on_or_before" do |time|
|
20
|
+
where(t[column_name].lteq time_object(time))
|
21
|
+
end
|
22
|
+
|
23
|
+
define_singleton_method :"#{prefix}before" do |time|
|
24
|
+
where(t[column_name].lt time_object(time))
|
25
|
+
end
|
26
|
+
|
27
|
+
define_singleton_method :"#{prefix}on_or_after_date" do |time|
|
28
|
+
where(t[column_name].gteq time.to_date.midnight.gmtime )
|
29
|
+
end
|
30
|
+
|
31
|
+
define_singleton_method :"#{prefix}on_or_after" do |time|
|
32
|
+
where(t[column_name].gteq time_object(time))
|
33
|
+
end
|
34
|
+
|
35
|
+
define_singleton_method :"#{prefix}after" do |time|
|
36
|
+
where(t[column_name].gt (time.is_a?(Date) ? time.to_time + 1.day : time ))
|
37
|
+
end
|
38
|
+
|
39
|
+
define_singleton_method :"#{prefix}on" do |day|
|
40
|
+
__send__(:"#{prefix}between", day.beginning_of_day, day.end_of_day)
|
41
|
+
end
|
42
|
+
|
43
|
+
define_singleton_method :"#{prefix}day" do |day|
|
44
|
+
__send__(:"#{prefix}on", day)
|
45
|
+
end
|
46
|
+
|
47
|
+
define_singleton_method :"#{prefix}last_24_hours" do
|
48
|
+
__send__(:"#{prefix}last_day")
|
49
|
+
end
|
50
|
+
|
51
|
+
[:minute, :hour].each do |time_unit|
|
52
|
+
define_singleton_method :"#{prefix}next_#{time_unit}" do
|
53
|
+
__send__(:"#{prefix}between", Time.now, 1.send(time_unit).from_now)
|
54
|
+
end
|
55
|
+
|
56
|
+
define_singleton_method :"#{prefix}last_#{time_unit}" do
|
57
|
+
__send__(:"#{prefix}between", 1.send(time_unit).ago, Time.now)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
[:seconds, :minutes, :hours].each do |time_unit|
|
62
|
+
define_singleton_method :"#{prefix}last_n_#{time_unit}" do |count|
|
63
|
+
__send__(:"#{prefix}between", count.send(time_unit).ago, Time.now)
|
64
|
+
end
|
65
|
+
|
66
|
+
define_singleton_method :"#{prefix}next_n_#{time_unit}" do |count|
|
67
|
+
__send__(:"#{prefix}between", Time.now, count.send(time_unit).from_now)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
define_singleton_method :"#{prefix}this_minute" do
|
72
|
+
__send__(:"#{prefix}between", Time.now.change(sec: 0), Time.now.change(sec: 59, usec: Rational(999999999, 1000)))
|
73
|
+
end
|
74
|
+
|
75
|
+
[:hour, :day, :week, :month, :year].each do |time_unit|
|
76
|
+
define_singleton_method :"#{prefix}this_#{time_unit}" do
|
77
|
+
__send__(:"#{prefix}between", 1.send(time_unit).ago.send(:"end_of_#{time_unit}"), Time.now.send(:"end_of_#{time_unit}"))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
define_common_scopes prefix, column_name
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def time_object(time)
|
87
|
+
time.is_a?(Date) ? time.to_time + 1.day : time
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
@@ -40,4 +40,18 @@ describe "Post" do
|
|
40
40
|
|
41
41
|
it_behaves_like 'date scopes', :show_until
|
42
42
|
end
|
43
|
+
|
44
|
+
describe 'providing column type' do
|
45
|
+
before(:all) do
|
46
|
+
define_model_class do
|
47
|
+
include_date_scopes_for :show_at, nil, :date
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'does not respond to time scopes' do
|
52
|
+
expect(Post).not_to respond_to(:last_n_minutes)
|
53
|
+
end
|
54
|
+
|
55
|
+
it_behaves_like 'date scopes', :show_at
|
56
|
+
end
|
43
57
|
end
|
@@ -1,197 +1,263 @@
|
|
1
1
|
|
2
|
+
shared_examples "between date scope" do |name|
|
3
|
+
context 'with time argument' do
|
4
|
+
# Not working right now
|
5
|
+
# include_examples 'between time scope', name, 1.day
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'with date argument' do
|
9
|
+
subject do
|
10
|
+
test_class.send "#{prefix}#{name}", *arguments
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:after_threshold_obj) { test_class.create! date_column => top_threshold.to_date - 1.second }
|
14
|
+
let(:at_top_threshold_obj) { test_class.create! date_column => top_threshold.to_date }
|
15
|
+
let(:at_bottom_threshold_obj) { test_class.create! date_column => bottom_threshold.to_date }
|
16
|
+
let(:before_threshold_obj) { test_class.create! date_column => bottom_threshold.to_date + 1.second }
|
17
|
+
|
18
|
+
it { should_not include after_threshold_obj }
|
19
|
+
it { should include at_top_threshold_obj }
|
20
|
+
it { should include at_bottom_threshold_obj }
|
21
|
+
it { should_not include before_threshold_obj }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
2
25
|
shared_examples "date scopes" do |date_column = :created_at, prefix = '' |
|
3
26
|
let(:test_class) { Post }
|
27
|
+
let(:prefix) { prefix }
|
28
|
+
let(:date_column) { date_column }
|
29
|
+
|
4
30
|
describe "date scopes" do
|
5
31
|
before(:all) { Timecop.freeze Time.local(2013,02,15,06,30) }
|
6
32
|
|
7
|
-
let(:last_year_obj) { test_class.create! date_column => 1.year.ago }
|
8
|
-
let(:last_month_obj) { test_class.create! date_column => 1.month.ago.to_date }
|
9
|
-
let(:beginning_of_month_obj) { test_class.create! date_column => Date.today.beginning_of_month }
|
10
|
-
let(:last_week_obj) { test_class.create! date_column => 7.days.ago.to_date }
|
11
|
-
let(:beginning_of_week_obj) { test_class.create! date_column => Date.today.beginning_of_week }
|
12
|
-
let(:yesterday_obj) { test_class.create! date_column => Date.yesterday }
|
13
|
-
let(:today_obj) { test_class.create! date_column => Date.today }
|
14
|
-
|
15
33
|
describe ":between" do
|
16
|
-
subject { test_class.send("#{prefix}between",
|
34
|
+
subject { test_class.send("#{prefix}between", 6.days.ago.to_date, 3.day.ago.to_date) }
|
17
35
|
|
18
|
-
|
19
|
-
|
20
|
-
|
36
|
+
let(:after_threshold_obj) { test_class.create! date_column => 2.days.ago.to_date }
|
37
|
+
let(:at_top_threshold_obj) { test_class.create! date_column => 3.days.ago.to_date }
|
38
|
+
let(:at_bottom_threshold_obj) { test_class.create! date_column => 6.days.ago.to_date }
|
39
|
+
let(:before_threshold_obj) { test_class.create! date_column => 7.days.ago.to_date }
|
40
|
+
|
41
|
+
it { should_not include after_threshold_obj }
|
42
|
+
it { should include at_top_threshold_obj }
|
43
|
+
it { should include at_bottom_threshold_obj }
|
44
|
+
it { should_not include before_threshold_obj }
|
21
45
|
end
|
22
46
|
|
23
47
|
describe ":after" do
|
24
|
-
subject { test_class.send("#{prefix}after",
|
48
|
+
subject { test_class.send("#{prefix}after", 3.days.ago.to_date) }
|
25
49
|
|
26
|
-
|
27
|
-
|
28
|
-
|
50
|
+
let(:after_threshold_obj) { test_class.create! date_column => 2.days.ago.to_date }
|
51
|
+
let(:on_threshold_obj) { test_class.create! date_column => 3.days.ago.to_date }
|
52
|
+
let(:before_threshold_obj) { test_class.create! date_column => 4.days.ago.to_date }
|
53
|
+
|
54
|
+
it { should include after_threshold_obj }
|
55
|
+
it { should_not include on_threshold_obj }
|
56
|
+
it { should_not include before_threshold_obj }
|
29
57
|
end
|
30
58
|
|
31
59
|
describe ":before" do
|
32
|
-
subject { test_class.send("#{prefix}before",
|
33
|
-
|
34
|
-
it { should include last_week_obj }
|
35
|
-
it { should include yesterday_obj }
|
36
|
-
it { should_not include today_obj }
|
37
|
-
end
|
60
|
+
subject { test_class.send("#{prefix}before", 3.days.ago.to_date) }
|
38
61
|
|
39
|
-
|
40
|
-
|
62
|
+
let(:after_threshold_obj) { test_class.create! date_column => 4.days.ago.to_date }
|
63
|
+
let(:on_threshold_obj) { test_class.create! date_column => 3.days.ago.to_date }
|
64
|
+
let(:before_threshold_obj) { test_class.create! date_column => 2.days.ago.to_date }
|
41
65
|
|
42
|
-
it {
|
43
|
-
it { should_not include
|
44
|
-
it {
|
66
|
+
it { should include after_threshold_obj }
|
67
|
+
it { should_not include on_threshold_obj }
|
68
|
+
it { should_not include before_threshold_obj }
|
45
69
|
end
|
46
70
|
|
47
|
-
describe ":
|
48
|
-
subject { test_class.send("#{prefix}
|
71
|
+
describe ":on_or_after" do
|
72
|
+
subject { test_class.send("#{prefix}on_or_after", 3.days.ago.to_date) }
|
49
73
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
74
|
+
let(:after_threshold_obj) { test_class.create! date_column => 2.days.ago.to_date }
|
75
|
+
let(:on_threshold_obj) { test_class.create! date_column => 3.days.ago.to_date }
|
76
|
+
let(:before_threshold_obj) { test_class.create! date_column => 4.days.ago.to_date }
|
54
77
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
it { should_not include last_week_obj }
|
59
|
-
it { should include yesterday_obj }
|
60
|
-
it { should include today_obj }
|
78
|
+
it { should include after_threshold_obj }
|
79
|
+
it { should include on_threshold_obj }
|
80
|
+
it { should_not include before_threshold_obj }
|
61
81
|
end
|
62
82
|
|
63
|
-
describe ":
|
64
|
-
subject { test_class.send("#{prefix}
|
83
|
+
describe ":on_or_before" do
|
84
|
+
subject { test_class.send("#{prefix}on_or_before", 3.days.ago) }
|
65
85
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
it { should include yesterday_obj }
|
70
|
-
end
|
86
|
+
let(:after_threshold_obj) { test_class.create! date_column => 4.days.ago.to_date }
|
87
|
+
let(:on_threshold_obj) { test_class.create! date_column => 3.days.ago.to_date }
|
88
|
+
let(:before_threshold_obj) { test_class.create! date_column => 2.days.ago.to_date }
|
71
89
|
|
72
|
-
|
73
|
-
|
90
|
+
it { should include after_threshold_obj }
|
91
|
+
it { should include on_threshold_obj }
|
92
|
+
it { should_not include before_threshold_obj }
|
93
|
+
end
|
74
94
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
95
|
+
describe ":today" do
|
96
|
+
let(:top_threshold) { Time.now.beginning_of_day }
|
97
|
+
let(:bottom_threshold) { Time.now.end_of_day }
|
98
|
+
let(:arguments) { [] }
|
99
|
+
include_examples 'between date scope','today'
|
79
100
|
end
|
80
101
|
|
81
|
-
describe
|
82
|
-
|
102
|
+
describe ":yesterday" do
|
103
|
+
let(:top_threshold) { 1.day.ago.beginning_of_day }
|
104
|
+
let(:bottom_threshold) { 1.day.ago.end_of_day }
|
105
|
+
let(:arguments) { [] }
|
106
|
+
include_examples 'between date scope','yesterday'
|
107
|
+
end
|
83
108
|
|
84
|
-
|
85
|
-
let(:
|
86
|
-
let(:
|
109
|
+
describe ":tomorrow" do
|
110
|
+
let(:top_threshold) { 1.day.from_now.beginning_of_day }
|
111
|
+
let(:bottom_threshold) { 1.day.from_now.end_of_day }
|
112
|
+
let(:arguments) { [] }
|
113
|
+
include_examples 'between date scope','tomorrow'
|
114
|
+
end
|
87
115
|
|
88
|
-
|
89
|
-
|
90
|
-
|
116
|
+
describe ":next_day" do
|
117
|
+
let(:bottom_threshold) { 1.day.from_now }
|
118
|
+
let(:top_threshold) { Time.now }
|
119
|
+
let(:arguments) { [] }
|
120
|
+
include_examples 'between date scope','next_day'
|
91
121
|
end
|
92
122
|
|
93
|
-
describe
|
94
|
-
|
123
|
+
describe ":next_week" do
|
124
|
+
let(:bottom_threshold) { 1.week.from_now }
|
125
|
+
let(:top_threshold) { Time.now }
|
126
|
+
let(:arguments) { [] }
|
127
|
+
include_examples 'between date scope','next_week'
|
128
|
+
end
|
95
129
|
|
96
|
-
|
97
|
-
let(:
|
98
|
-
let(:
|
130
|
+
describe ":next_month" do
|
131
|
+
let(:bottom_threshold) { 1.month.from_now }
|
132
|
+
let(:top_threshold) { Time.now }
|
133
|
+
let(:arguments) { [] }
|
134
|
+
include_examples 'between date scope','next_month'
|
135
|
+
end
|
99
136
|
|
100
|
-
|
101
|
-
|
102
|
-
|
137
|
+
describe ":next_year" do
|
138
|
+
let(:bottom_threshold) { 1.year.from_now }
|
139
|
+
let(:top_threshold) { Time.now }
|
140
|
+
let(:arguments) { [] }
|
141
|
+
include_examples 'between date scope','next_year'
|
103
142
|
end
|
104
143
|
|
105
|
-
describe
|
106
|
-
|
144
|
+
describe ":last_day" do
|
145
|
+
let(:top_threshold) { 1.day.ago }
|
146
|
+
let(:bottom_threshold) { Time.now }
|
147
|
+
let(:arguments) { [] }
|
148
|
+
include_examples 'between date scope','last_day'
|
149
|
+
end
|
107
150
|
|
108
|
-
|
109
|
-
let(:
|
110
|
-
let(:
|
151
|
+
describe ":last_week" do
|
152
|
+
let(:top_threshold) { 1.week.ago }
|
153
|
+
let(:bottom_threshold) { Time.now }
|
154
|
+
let(:arguments) { [] }
|
155
|
+
include_examples 'between date scope','last_week'
|
156
|
+
end
|
111
157
|
|
112
|
-
|
113
|
-
|
114
|
-
|
158
|
+
describe ":last_month" do
|
159
|
+
let(:top_threshold) { 1.month.ago }
|
160
|
+
let(:bottom_threshold) { Time.now }
|
161
|
+
let(:arguments) { [] }
|
162
|
+
include_examples 'between date scope','last_month'
|
115
163
|
end
|
116
164
|
|
117
|
-
describe
|
118
|
-
|
165
|
+
describe ":last_year" do
|
166
|
+
let(:top_threshold) { 1.year.ago }
|
167
|
+
let(:bottom_threshold) { Time.now }
|
168
|
+
let(:arguments) { [] }
|
169
|
+
include_examples 'between date scope','last_year'
|
170
|
+
end
|
119
171
|
|
120
|
-
|
121
|
-
let(:
|
122
|
-
let(:
|
172
|
+
describe ":last_n_days" do
|
173
|
+
let(:top_threshold) { 3.days.ago }
|
174
|
+
let(:bottom_threshold) { Time.now }
|
175
|
+
let(:arguments) { [3] }
|
176
|
+
include_examples 'between date scope','last_n_days'
|
177
|
+
end
|
123
178
|
|
124
|
-
|
125
|
-
|
126
|
-
|
179
|
+
describe ":last_n_weeks" do
|
180
|
+
let(:top_threshold) { 3.weeks.ago }
|
181
|
+
let(:bottom_threshold) { Time.now }
|
182
|
+
let(:arguments) { [3] }
|
183
|
+
include_examples 'between date scope','last_n_weeks'
|
127
184
|
end
|
128
185
|
|
129
|
-
describe
|
130
|
-
|
186
|
+
describe ":last_n_months" do
|
187
|
+
let(:top_threshold) { 3.months.ago }
|
188
|
+
let(:bottom_threshold) { Time.now }
|
189
|
+
let(:arguments) { [3] }
|
190
|
+
include_examples 'between date scope','last_n_months'
|
191
|
+
end
|
131
192
|
|
132
|
-
|
133
|
-
let(:
|
134
|
-
let(:
|
193
|
+
describe ":last_n_years" do
|
194
|
+
let(:top_threshold) { 3.years.ago }
|
195
|
+
let(:bottom_threshold) { Time.now }
|
196
|
+
let(:arguments) { [3] }
|
197
|
+
include_examples 'between date scope','last_n_years'
|
198
|
+
end
|
135
199
|
|
136
|
-
|
137
|
-
|
138
|
-
|
200
|
+
describe ":next_n_days" do
|
201
|
+
let(:top_threshold) { Time.now }
|
202
|
+
let(:bottom_threshold) { 3.days.from_now }
|
203
|
+
let(:arguments) { [3] }
|
204
|
+
include_examples 'between date scope','next_n_days'
|
139
205
|
end
|
140
206
|
|
141
|
-
describe
|
142
|
-
|
207
|
+
describe ":next_n_weeks" do
|
208
|
+
let(:top_threshold) { Time.now }
|
209
|
+
let(:bottom_threshold) { 3.weeks.from_now }
|
210
|
+
let(:arguments) { [3] }
|
211
|
+
include_examples 'between date scope','next_n_weeks'
|
212
|
+
end
|
143
213
|
|
144
|
-
|
145
|
-
let(:
|
146
|
-
let(:
|
214
|
+
describe ":next_n_months" do
|
215
|
+
let(:top_threshold) { Time.now }
|
216
|
+
let(:bottom_threshold) { 3.months.from_now }
|
217
|
+
let(:arguments) { [3] }
|
218
|
+
include_examples 'between date scope','next_n_months'
|
219
|
+
end
|
147
220
|
|
148
|
-
|
149
|
-
|
150
|
-
|
221
|
+
describe ":next_n_years" do
|
222
|
+
let(:top_threshold) { Time.now }
|
223
|
+
let(:bottom_threshold) { 3.years.from_now }
|
224
|
+
let(:arguments) { [3] }
|
225
|
+
include_examples 'between date scope','next_n_years'
|
151
226
|
end
|
152
227
|
|
153
228
|
describe ":last_30_days" do
|
154
|
-
|
229
|
+
let(:top_threshold) { 30.days.ago }
|
230
|
+
let(:bottom_threshold) { Time.now }
|
231
|
+
let(:arguments) { [] }
|
232
|
+
include_examples 'between date scope','last_30_days'
|
233
|
+
end
|
155
234
|
|
156
|
-
|
157
|
-
|
158
|
-
|
235
|
+
describe ":this_day" do
|
236
|
+
let(:top_threshold) { Time.now.beginning_of_day }
|
237
|
+
let(:bottom_threshold) { Time.now.end_of_day }
|
238
|
+
let(:arguments) { [] }
|
239
|
+
include_examples 'between date scope','this_day'
|
159
240
|
end
|
160
241
|
|
161
242
|
describe ":this_week" do
|
162
|
-
|
163
|
-
|
164
|
-
let(:
|
165
|
-
|
166
|
-
let(:after_week) { test_class.create! date_column => Date.today.beginning_of_week + 1.minute }
|
167
|
-
|
168
|
-
it { should_not include before_week }
|
169
|
-
it { should include at_beginning_of_week }
|
170
|
-
it { should include after_week }
|
243
|
+
let(:top_threshold) { Time.now.beginning_of_week }
|
244
|
+
let(:bottom_threshold) { Time.now.end_of_week }
|
245
|
+
let(:arguments) { [] }
|
246
|
+
include_examples 'between date scope','this_week'
|
171
247
|
end
|
172
248
|
|
173
249
|
describe ":this_month" do
|
174
|
-
|
175
|
-
|
176
|
-
let(:
|
177
|
-
|
178
|
-
let(:after_month) { test_class.create! date_column => Date.today.beginning_of_month + 1.minute }
|
179
|
-
|
180
|
-
it { should_not include before_month }
|
181
|
-
it { should include at_beginning_of_month }
|
182
|
-
it { should include after_month }
|
250
|
+
let(:top_threshold) { Time.now.beginning_of_month }
|
251
|
+
let(:bottom_threshold) { Time.now.end_of_month }
|
252
|
+
let(:arguments) { [] }
|
253
|
+
include_examples 'between date scope','this_month'
|
183
254
|
end
|
184
255
|
|
185
256
|
describe ":this_year" do
|
186
|
-
|
187
|
-
|
188
|
-
let(:
|
189
|
-
|
190
|
-
let(:after_year) { test_class.create! date_column => Date.today.beginning_of_year + 1.minute }
|
191
|
-
|
192
|
-
it { should_not include before_year }
|
193
|
-
it { should include at_beginning_of_year }
|
194
|
-
it { should include after_year }
|
257
|
+
let(:top_threshold) { Time.now.beginning_of_year }
|
258
|
+
let(:bottom_threshold) { Time.now.end_of_year }
|
259
|
+
let(:arguments) { [] }
|
260
|
+
include_examples 'between date scope','this_year'
|
195
261
|
end
|
196
262
|
end
|
197
263
|
end
|