by_star 2.2.1 → 3.0.0

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.
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
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'by cweek' do
4
+
5
+ describe '#by_cweek' do
6
+
7
+ context 'point-in-time' do
8
+ subject { Post.by_cweek('2014-01-02') }
9
+ it { expect(subject.count).to eql(4) }
10
+ end
11
+
12
+ context 'timespan' do
13
+ subject { Event.by_cweek(1) }
14
+ it { expect(subject.count).to eql(7) }
15
+ end
16
+
17
+ context 'timespan strict' do
18
+ subject { Event.by_cweek(Date.parse('2014-01-01'), strict: true) }
19
+ it { expect(subject.count).to eql(0) }
20
+ end
21
+
22
+ context 'with :year option' do
23
+
24
+ context 'point-in-time' do
25
+ subject { Post.by_cweek(53, year: 2013) }
26
+ it { expect(subject.count).to eql(4) }
27
+ end
28
+
29
+ context 'timespan' do
30
+ subject { Event.by_cweek(53, year: 2013) }
31
+ it { expect(subject.count).to eql(7) }
32
+ end
33
+
34
+ context 'timespan strict' do
35
+ subject { Event.by_cweek(53, year: 2013, strict: true) }
36
+ it { expect(subject.count).to eql(0) }
37
+ end
38
+ end
39
+
40
+ it 'should raise an error when given an invalid argument' do
41
+ expect { Post.by_cweek(0) }.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53')
42
+ expect { Post.by_cweek(54) }.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53')
43
+ end
44
+
45
+ it 'should be able to use an alternative field' do
46
+ expect(Event.by_cweek(field: 'end_time').count).to eq 3
47
+ end
48
+
49
+ context ':start_day option' do
50
+ subject { Post.by_cweek('2014-01-02', start_day: :thursday) }
51
+ it { expect(subject.count).to eql(1) }
52
+ end
53
+ end
54
+ end
@@ -1,108 +1,96 @@
1
- require 'spec_helper'
2
-
3
- shared_examples_for 'by day' do
4
-
5
- describe '#by_day' do
6
-
7
- context 'point-in-time' do
8
- subject { Post.by_day('2014-01-01') }
9
- its(:count){ should eq 2 }
10
- end
11
-
12
- context 'timespan' do
13
- subject { Event.by_day(Time.parse '2014-01-01') }
14
- its(:count){ should eq 5 }
15
- end
16
-
17
- context 'timespan strict' do
18
- subject { Event.by_day(Date.parse('2014-01-01'), strict: true) }
19
- its(:count){ should eq 0 }
20
- end
21
-
22
- it 'should be able to use an alternative field' do
23
- Event.by_day(:field => 'end_time').count.should eq 0
24
- end
25
-
26
- it 'should support :offset option' do
27
- Post.by_day('2014-01-01', :offset => -16.hours).count.should eq 1
28
- end
29
- end
30
-
31
- describe '#today' do # 2014-01-01
32
-
33
- context 'point-in-time' do
34
- subject { Post.today }
35
- its(:count){ should eq 2 }
36
- end
37
-
38
- context 'timespan' do
39
- subject { Event.today }
40
- its(:count){ should eq 5 }
41
- end
42
-
43
- context 'timespan strict' do
44
- subject { Event.today(strict: true) }
45
- its(:count){ should eq 0 }
46
- end
47
-
48
- it 'should be able to use an alternative field' do
49
- Event.today(:field => 'created_at').count.should eq 2
50
- end
51
-
52
- it 'should support :offset option' do
53
- Post.today(:offset => -24.hours).count.should eq 1
54
- end
55
- end
56
-
57
- describe '#yesterday' do # 2013-12-31
58
-
59
- context 'point-in-time' do
60
- subject { Post.yesterday }
61
- its(:count){ should eq 1 }
62
- end
63
-
64
- context 'timespan' do
65
- subject { Event.yesterday }
66
- its(:count){ should eq 5 }
67
- end
68
-
69
- context 'timespan strict' do
70
- subject { Event.yesterday(strict: true) }
71
- its(:count){ should eq 0 }
72
- end
73
-
74
- it 'should be able to use an alternative field' do
75
- Event.yesterday(:field => 'created_at').count.should eq 1
76
- end
77
-
78
- it 'should support :offset option' do
79
- Post.yesterday(:offset => 24.hours).count.should eq 2
80
- end
81
- end
82
-
83
- describe '#tomorrow' do # 2014-01-02
84
-
85
- context 'point-in-time' do
86
- subject { Post.tomorrow }
87
- its(:count){ should eq 0 }
88
- end
89
-
90
- context 'timespan' do
91
- subject { Event.tomorrow }
92
- its(:count){ should eq 5 }
93
- end
94
-
95
- context 'timespan strict' do
96
- subject { Event.tomorrow(strict: true) }
97
- its(:count){ should eq 0 }
98
- end
99
-
100
- it 'should be able to use an alternative field' do
101
- Event.tomorrow(:field => 'created_at').count.should eq 0
102
- end
103
-
104
- it 'should support :offset option' do
105
- Post.tomorrow(:offset => -24.hours).count.should eq 2
106
- end
107
- end
108
- end
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'by day' do
4
+
5
+ describe '#by_day' do
6
+
7
+ context 'point-in-time' do
8
+ it { expect(Post.by_day('2014-01-01').count).to eql(2) }
9
+ end
10
+
11
+ context 'timespan' do
12
+ it { expect(Event.by_day(Time.zone.parse '2014-01-01').count).to eql(5) }
13
+ end
14
+
15
+ context 'timespan strict' do
16
+ it { expect(Event.by_day(Date.parse('2014-01-01'), strict: true).count).to eql(0) }
17
+ end
18
+
19
+ it 'should be able to use an alternative field' do
20
+ expect(Event.by_day(field: 'end_time').count).to eql(0)
21
+ end
22
+
23
+ it 'should support :offset option' do
24
+ expect(Post.by_day('2014-01-01', offset: -16.hours).count).to eq(1)
25
+ end
26
+ end
27
+
28
+ describe '#today' do # 2014-01-01
29
+
30
+ context 'point-in-time' do
31
+ it { expect(Post.today.count).to eql(2) }
32
+ end
33
+
34
+ context 'timespan' do
35
+ it { expect(Event.today.count).to eql(5) }
36
+ end
37
+
38
+ context 'timespan strict' do
39
+ it { expect(Event.today(strict: true).count).to eql(0) }
40
+ end
41
+
42
+ it 'should be able to use an alternative field' do
43
+ expect(Event.today(field: 'created_at').count).to eql(2)
44
+ end
45
+
46
+ it 'should support :offset option' do
47
+ expect(Post.today(offset: -24.hours).count).to eql(1)
48
+ end
49
+ end
50
+
51
+ describe '#yesterday' do # 2013-12-31
52
+
53
+ context 'point-in-time' do
54
+ it { expect(Post.yesterday.count).to eql(1) }
55
+ end
56
+
57
+ context 'timespan' do
58
+ it { expect(Event.yesterday.count).to eql(5) }
59
+ end
60
+
61
+ context 'timespan strict' do
62
+ it { expect(Event.yesterday(strict: true).count).to eql(0) }
63
+ end
64
+
65
+ it 'should be able to use an alternative field' do
66
+ expect(Event.yesterday(field: 'created_at').count).to eql(1)
67
+ end
68
+
69
+ it 'should support :offset option' do
70
+ expect(Post.yesterday(offset: 24.hours).count).to eql(2)
71
+ end
72
+ end
73
+
74
+ describe '#tomorrow' do # 2014-01-02
75
+
76
+ context 'point-in-time' do
77
+ it { expect(Post.tomorrow.count).to eql(0) }
78
+ end
79
+
80
+ context 'timespan' do
81
+ it { expect(Event.tomorrow.count).to eql(5) }
82
+ end
83
+
84
+ context 'timespan strict' do
85
+ it { expect(Event.tomorrow(strict: true).count).to eql(0) }
86
+ end
87
+
88
+ it 'should be able to use an alternative field' do
89
+ expect(Event.tomorrow(field: 'created_at').count).to eql(0)
90
+ end
91
+
92
+ it 'should support :offset option' do
93
+ expect(Post.tomorrow(offset: -24.hours).count).to eql(2)
94
+ end
95
+ end
96
+ end
@@ -1,153 +1,172 @@
1
- require 'spec_helper'
2
-
3
- shared_examples_for 'by direction' do
4
-
5
- describe '#before' do
6
-
7
- context 'point-in-time' do
8
- subject { Post.before(Date.parse '2014-01-05') }
9
- its(:count){ should eq 12 }
10
- end
11
-
12
- context 'timespan' do
13
- subject { Event.before(Time.parse '2014-01-05') }
14
- its(:count){ should eq 13 }
15
- end
16
-
17
- context 'timespan strict' do
18
- subject { Event.before('2014-01-05', strict: true) }
19
- its(:count){ should eq 13 }
20
- end
21
-
22
- context 'alternative field' do
23
- subject { Event.before('2014-01-05', field: 'created_at') }
24
- its(:count){ should eq 12 }
25
- end
26
-
27
- context 'with default scope' do
28
- subject { Appointment.before('2014-01-05', field: 'created_at') }
29
- its(:count){ should eq 4 }
30
- end
31
-
32
- context 'with scope as a query criteria' do
33
- subject { Post.before('2014-01-05', field: 'created_at', scope: Post.where(day_of_month: 5)) }
34
- its(:count){ should eq 1 }
35
- end
36
-
37
- context 'with scope as a proc' do
38
- subject { Post.before('2014-01-05', field: 'created_at', scope: ->{ where(day_of_month: 5) }) }
39
- its(:count){ should eq 1 }
40
- end
41
- end
42
-
43
- describe '#after' do
44
-
45
- context 'point-in-time' do
46
- subject { Post.after('2014-01-05') }
47
- its(:count){ should eq 10 }
48
- end
49
-
50
- context 'timespan' do
51
- subject { Event.after(Date.parse '2014-01-05') }
52
- its(:count){ should eq 9 }
53
- end
54
-
55
- context 'timespan strict' do
56
- subject { Event.after('2014-01-05', strict: true) }
57
- its(:count){ should eq 9 }
58
- end
59
-
60
- context 'alternative field' do
61
- subject { Event.after('2014-01-05', field: 'created_at') }
62
- its(:count){ should eq 10 }
63
- end
64
-
65
- context 'with default scope' do
66
- subject { Appointment.after('2014-01-05', field: 'created_at') }
67
- its(:count){ should eq 3 }
68
- end
69
-
70
- context 'with scope as a query criteria' do
71
- subject { Post.after('2014-01-05', field: 'created_at', scope: Post.where(day_of_month: 5)) }
72
- its(:count){ should eq 1 }
73
- end
74
-
75
- context 'with scope as a proc' do
76
- subject { Post.after('2014-01-05', field: 'created_at', scope: ->{ where(day_of_month: 5) }) }
77
- its(:count){ should eq 1 }
78
- end
79
- end
80
-
81
- describe '#oldest and #newest' do
82
-
83
- context 'point-in-time' do
84
- it { Post.newest.created_at.should eq Time.zone.parse('2014-04-15 17:00:00') }
85
- it { Post.oldest.created_at.should eq Time.zone.parse('2013-11-01 17:00:00') }
86
- end
87
-
88
- context 'timespan' do
89
- it { Event.newest.created_at.should eq Time.zone.parse('2014-04-15 17:00:00') }
90
- it { Event.oldest.created_at.should eq Time.zone.parse('2013-11-01 17:00:00') }
91
- end
92
-
93
- context 'timespan strict' do
94
- it { Event.newest(strict: true).created_at.should eq Time.zone.parse('2014-04-15 17:00:00') }
95
- it { Event.oldest(strict: true).created_at.should eq Time.zone.parse('2013-11-01 17:00:00') }
96
- end
97
-
98
- context 'alternative field' do
99
- it { Event.newest(field: 'created_at').created_at.should eq Time.zone.parse('2014-04-15 17:00:00') }
100
- it { Event.oldest(field: 'created_at').created_at.should eq Time.zone.parse('2013-11-01 17:00:00') }
101
- end
102
-
103
- context 'with default scope' do
104
- it { Appointment.newest(field: 'created_at').created_at.should eq Time.zone.parse('2014-04-01 17:00:00') }
105
- it { Appointment.oldest(field: 'created_at').created_at.should eq Time.zone.parse('2013-11-01 17:00:00') }
106
- end
107
-
108
- context 'with scope as a query criteria' do
109
- it { Post.newest(field: 'created_at', scope: Post.where(day_of_month: 5)).created_at.should eq Time.zone.parse('2014-01-05 17:00:00') }
110
- it { Post.oldest(field: 'created_at', scope: Post.where(day_of_month: 5)).created_at.should eq Time.zone.parse('2013-12-05 17:00:00') }
111
- end
112
-
113
- context 'with scope as a proc' do
114
- it { Post.newest(field: 'created_at', scope: ->{ where(day_of_month: 5) }).created_at.should eq Time.zone.parse('2014-01-05 17:00:00') }
115
- it { Post.oldest(field: 'created_at', scope: ->{ where(day_of_month: 5) }).created_at.should eq Time.zone.parse('2013-12-05 17:00:00') }
116
- end
117
- end
118
-
119
- describe '#previous and #next' do
120
-
121
- context 'point-in-time' do
122
- subject { Post.where(created_at: Time.zone.parse('2014-01-10 17:00:00')).first }
123
- it{ subject.previous.created_at.should eq Time.zone.parse('2014-01-05 17:00:00') }
124
- it{ subject.next.created_at.should eq Time.zone.parse('2014-01-12 17:00:00') }
125
- end
126
-
127
- context 'timespan' do
128
- subject { Event.where(start_time: Time.zone.parse('2014-01-05 17:00:00')).first }
129
- it{ subject.previous.start_time.should eq Time.zone.parse('2013-12-31 17:00:00') }
130
- it{ subject.next.start_time.should eq Time.zone.parse('2014-01-07 17:00:00') }
131
- end
132
-
133
- context 'with default scope' do
134
- subject { Appointment.where(created_at: Time.zone.parse('2014-01-05 17:00:00')).first }
135
- it{ subject.previous.created_at.should eq Time.zone.parse('2014-01-01 17:00:00') }
136
- it{ subject.next.created_at.should eq Time.zone.parse('2014-02-01 17:00:00') }
137
- end
138
-
139
- context 'with scope as a query criteria' do
140
- subject { Post.where(created_at: Time.zone.parse('2014-01-05 17:00:00')).first }
141
- it{ subject.previous({ scope: Post.where(day_of_month: 5) }).created_at.should eq Time.zone.parse('2013-12-05 17:00:00') }
142
- it{ subject.next({ scope: Post.where(day_of_month: 1) }).created_at.should eq Time.zone.parse('2014-02-01 17:00:00') }
143
- end
144
-
145
- context 'with scope as a proc' do
146
- subject { Post.where(created_at: Time.zone.parse('2014-01-05 17:00:00')).first }
147
- it{ subject.previous({ scope: Proc.new{ where(day_of_month: 5) } }).created_at.should eq Time.zone.parse('2013-12-05 17:00:00') }
148
- it{ subject.previous({ scope: Proc.new{|record| where(day_of_month: record.day_of_month) } }).created_at.should eq Time.zone.parse('2013-12-05 17:00:00') }
149
- it{ subject.next({ scope: ->{ where(day_of_month: 1) } }).created_at.should eq Time.zone.parse('2014-02-01 17:00:00') }
150
- it{ subject.next({ scope: ->(record){ where(day_of_month: record.day_of_month - 4) } }).created_at.should eq Time.zone.parse('2014-02-01 17:00:00') }
151
- end
152
- end
153
- end
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'by direction' do
4
+
5
+ describe '#before' do
6
+
7
+ context 'point-in-time' do
8
+ subject { Post.before(Date.parse '2014-01-05') }
9
+ it { expect(subject.count).to eql(12) }
10
+ end
11
+
12
+ context 'timespan default' do
13
+ subject { Event.before(Time.zone.parse '2014-01-05') }
14
+ it { expect(subject.count).to eql(13) }
15
+ end
16
+
17
+ context 'timespan strict' do
18
+ subject { Event.before('2014-01-05', strict: true) }
19
+ it { expect(subject.count).to eql(13) }
20
+ end
21
+
22
+ context 'timespan not strict' do
23
+ subject { Event.before('2014-01-05', strict: false) }
24
+ it { expect(subject.count).to eql(13) }
25
+ end
26
+
27
+ context 'alternative field' do
28
+ subject { Event.before('2014-01-05', field: 'created_at') }
29
+ it { expect(subject.count).to eql(12) }
30
+ end
31
+
32
+ context 'with default scope' do
33
+ subject { Appointment.before('2014-01-05', field: 'created_at') }
34
+ it { expect(subject.count).to eql(4) }
35
+ end
36
+
37
+ context 'with scope as a query criteria' do
38
+ subject { Post.before('2014-01-05', field: 'created_at', scope: Post.where(day_of_month: 5)) }
39
+ it { expect(subject.count).to eql(1) }
40
+ end
41
+
42
+ context 'with scope as a proc' do
43
+ subject { Post.before('2014-01-05', field: 'created_at', scope: ->{ where(day_of_month: 5) }) }
44
+ it { expect(subject.count).to eql(1) }
45
+ end
46
+ end
47
+
48
+ describe '#after' do
49
+
50
+ context 'point-in-time' do
51
+ subject { Post.after('2014-01-05') }
52
+ it { expect(subject.count).to eql(10) }
53
+ end
54
+
55
+ context 'timespan default' do
56
+ subject { Event.after(Date.parse '2014-01-05') }
57
+ it { expect(subject.count).to eql(9) }
58
+ end
59
+
60
+ context 'timespan strict' do
61
+ subject { Event.after('2014-01-05', strict: true) }
62
+ it { expect(subject.count).to eql(9) }
63
+ end
64
+
65
+ context 'timespan not strict' do
66
+ subject { Event.after('2014-01-05', strict: false) }
67
+ it { expect(subject.count).to eql(9) }
68
+ end
69
+
70
+ context 'alternative field' do
71
+ subject { Event.after('2014-01-05', field: 'created_at') }
72
+ it { expect(subject.count).to eql(10) }
73
+ end
74
+
75
+ context 'with default scope' do
76
+ subject { Appointment.after('2014-01-05', field: 'created_at') }
77
+ it { expect(subject.count).to eql(3) }
78
+ end
79
+
80
+ context 'with scope as a query criteria' do
81
+ subject { Post.after('2014-01-05', field: 'created_at', scope: Post.where(day_of_month: 5)) }
82
+ it { expect(subject.count).to eql(1) }
83
+ end
84
+
85
+ context 'with scope as a proc' do
86
+ subject { Post.after('2014-01-05', field: 'created_at', scope: ->{ where(day_of_month: 5) }) }
87
+ it { expect(subject.count).to eql(1) }
88
+ end
89
+ end
90
+
91
+ describe '#oldest and #newest' do
92
+
93
+ context 'point-in-time' do
94
+ it { expect(Post.newest.created_at).to eq Time.zone.parse('2014-04-15 17:00:00') }
95
+ it { expect(Post.oldest.created_at).to eq Time.zone.parse('2013-11-01 17:00:00') }
96
+ end
97
+
98
+ context 'timespan' do
99
+ it { expect(Event.newest.created_at).to eq Time.zone.parse('2014-04-15 17:00:00') }
100
+ it { expect(Event.oldest.created_at).to eq Time.zone.parse('2013-11-01 17:00:00') }
101
+ end
102
+
103
+ context 'timespan strict' do
104
+ it { expect(Event.newest(strict: true).created_at).to eq Time.zone.parse('2014-04-15 17:00:00') }
105
+ it { expect(Event.oldest(strict: true).created_at).to eq Time.zone.parse('2013-11-01 17:00:00') }
106
+ end
107
+
108
+ context 'alternative field' do
109
+ it { expect(Event.newest(field: 'created_at').created_at).to eq Time.zone.parse('2014-04-15 17:00:00') }
110
+ it { expect(Event.oldest(field: 'created_at').created_at).to eq Time.zone.parse('2013-11-01 17:00:00') }
111
+ end
112
+
113
+ context 'with default scope' do
114
+ it { expect(Appointment.newest(field: 'created_at').created_at).to eq Time.zone.parse('2014-04-01 17:00:00') }
115
+ it { expect(Appointment.oldest(field: 'created_at').created_at).to eq Time.zone.parse('2013-11-01 17:00:00') }
116
+ end
117
+
118
+ context 'with scope as a query criteria' do
119
+ it { expect(Post.newest(field: 'created_at', scope: Post.where(day_of_month: 5)).created_at).to eq Time.zone.parse('2014-01-05 17:00:00') }
120
+ it { expect(Post.oldest(field: 'created_at', scope: Post.where(day_of_month: 5)).created_at).to eq Time.zone.parse('2013-12-05 17:00:00') }
121
+ end
122
+
123
+ context 'with scope as a proc' do
124
+ it { expect(Post.newest(field: 'created_at', scope: ->{ where(day_of_month: 5) }).created_at).to eq Time.zone.parse('2014-01-05 17:00:00') }
125
+ it { expect(Post.oldest(field: 'created_at', scope: ->{ where(day_of_month: 5) }).created_at).to eq Time.zone.parse('2013-12-05 17:00:00') }
126
+ end
127
+ end
128
+
129
+ describe '#previous and #next' do
130
+
131
+ context 'point-in-time' do
132
+ subject { Post.where(created_at: Time.zone.parse('2014-01-10 17:00:00')).first }
133
+ it{ expect(subject.previous.created_at).to eq Time.zone.parse('2014-01-05 17:00:00') }
134
+ it{ expect(subject.next.created_at).to eq Time.zone.parse('2014-01-12 17:00:00') }
135
+ end
136
+
137
+ context 'timespan' do
138
+ subject { Event.where(start_time: Time.zone.parse('2014-01-05 17:00:00')).first }
139
+ it{ expect(subject.previous.start_time).to eq Time.zone.parse('2013-12-31 17:00:00') }
140
+ it{ expect(subject.next.start_time).to eq Time.zone.parse('2014-01-07 17:00:00') }
141
+ end
142
+
143
+ context 'with default scope' do
144
+ subject { Appointment.where(created_at: Time.zone.parse('2014-01-05 17:00:00')).first }
145
+ it{ expect(subject.previous.created_at).to eq Time.zone.parse('2014-01-01 17:00:00') }
146
+ it{ expect(subject.next.created_at).to eq Time.zone.parse('2014-02-01 17:00:00') }
147
+ end
148
+
149
+ context 'with scope as a query criteria' do
150
+ subject { Post.where(created_at: Time.zone.parse('2014-01-05 17:00:00')).first }
151
+ it{ expect(subject.previous({ scope: Post.where(day_of_month: 5) }).created_at).to eq Time.zone.parse('2013-12-05 17:00:00') }
152
+ it{ expect(subject.next({ scope: Post.where(day_of_month: 1) }).created_at).to eq Time.zone.parse('2014-02-01 17:00:00') }
153
+ end
154
+
155
+ context 'with scope as a proc' do
156
+ subject { Post.where(created_at: Time.zone.parse('2014-01-05 17:00:00')).first }
157
+ it{ expect(subject.previous({ scope: Proc.new{ where(day_of_month: 5) } }).created_at).to eq Time.zone.parse('2013-12-05 17:00:00') }
158
+ it{ expect(subject.previous({ scope: Proc.new{|record| where(day_of_month: record.day_of_month) } }).created_at).to eq Time.zone.parse('2013-12-05 17:00:00') }
159
+ it{ expect(subject.next({ scope: ->{ where(day_of_month: 1) } }).created_at).to eq Time.zone.parse('2014-02-01 17:00:00') }
160
+ it{ expect(subject.next({ scope: ->(record){ where(day_of_month: record.day_of_month - 4) } }).created_at).to eq Time.zone.parse('2014-02-01 17:00:00') }
161
+ end
162
+
163
+ context 'specify a field' do
164
+ subject { Post.where(created_at: Time.zone.parse('2014-01-01 17:00:00')).first }
165
+ it{ expect(subject.previous.created_at).to eq Time.zone.parse('2013-12-31 17:00:00') }
166
+ it{ expect(subject.next.created_at).to eq Time.zone.parse('2014-01-05 17:00:00') }
167
+ it{ expect(subject.previous(field: 'updated_at').created_at).to eq Time.zone.parse('2013-12-31 17:00:00') }
168
+ it{ expect(subject.next(field: 'updated_at').created_at).to eq Time.zone.parse('2014-01-01 17:00:00') }
169
+ end
170
+
171
+ end
172
+ end