chronological 0.0.5 → 0.0.6
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.
- data/lib/chronological.rb +5 -116
- data/lib/chronological/absolute_timeframe.rb +98 -0
- data/lib/chronological/base.rb +41 -0
- data/lib/chronological/relative_timeframe.rb +57 -0
- data/lib/chronological/version.rb +1 -1
- data/spec/{chronological_spec.rb → absolute_timeframe_spec.rb} +72 -218
- data/spec/base_spec.rb +230 -0
- data/spec/relative_timeframe_spec.rb +207 -0
- data/spec/spec_helper.rb +15 -2
- metadata +11 -4
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BaseChronologicable < ActiveRecord::Base
|
4
|
+
extend Chronological::Base
|
5
|
+
|
6
|
+
base_timeframe :start_date_field => :started_on,
|
7
|
+
:start_time_field => :started_at,
|
8
|
+
:end_date_field => :ended_on,
|
9
|
+
:end_time_field => :ended_at
|
10
|
+
|
11
|
+
private
|
12
|
+
def has_absolute_timeframe?
|
13
|
+
started_at.present? && ended_at.present?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Chronological::Base do
|
18
|
+
let(:started_at) { nil }
|
19
|
+
let(:ended_at) { nil }
|
20
|
+
|
21
|
+
let(:chronologicable) do
|
22
|
+
BaseChronologicable.new(
|
23
|
+
:started_at => started_at,
|
24
|
+
:ended_at => ended_at
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#started_on' do
|
29
|
+
context 'when #started_at is set' do
|
30
|
+
context 'to a string' do
|
31
|
+
let(:started_at) { '2012-07-26 03:15:12' }
|
32
|
+
|
33
|
+
it 'properly converts the date' do
|
34
|
+
chronologicable.started_on.should eql Time.utc(2012, 7, 26, 3, 15, 12).to_date
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'to a date' do
|
39
|
+
let(:started_at) { Time.utc(2012, 7, 26, 3, 15, 12) }
|
40
|
+
|
41
|
+
it 'properly converts the date' do
|
42
|
+
chronologicable.started_on.should eql Time.utc(2012, 7, 26, 3, 15, 12).to_date
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when #started_at is not set' do
|
48
|
+
let(:started_at) { nil }
|
49
|
+
|
50
|
+
it 'is nil' do
|
51
|
+
chronologicable.started_on.should be_nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#ended_on' do
|
57
|
+
context 'when #ended_at is set' do
|
58
|
+
context 'to a string' do
|
59
|
+
let(:ended_at) { '2012-07-26 03:15:12' }
|
60
|
+
|
61
|
+
it 'properly converts the date' do
|
62
|
+
chronologicable.ended_on.should eql Time.utc(2012, 7, 26, 3, 15, 12).to_date
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'to a date' do
|
67
|
+
let(:ended_at) { Time.utc(2012, 7, 26, 3, 15, 12) }
|
68
|
+
|
69
|
+
it 'properly converts the date' do
|
70
|
+
chronologicable.ended_on.should eql Time.utc(2012, 7, 26, 3, 15, 12).to_date
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when #ended_at is not set' do
|
76
|
+
let(:ended_at) { nil }
|
77
|
+
|
78
|
+
it 'is nil' do
|
79
|
+
chronologicable.ended_on.should be_nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#duration' do
|
85
|
+
context 'when the chronologicable represents something with a duration' do
|
86
|
+
before { chronologicable.should_receive(:duration_in_seconds).any_number_of_times.and_return(6263) }
|
87
|
+
|
88
|
+
it 'is a hash with the correct hours' do
|
89
|
+
chronologicable.duration[:hours].should eql 1
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'is a hash with the correct minutes' do
|
93
|
+
chronologicable.duration[:minutes].should eql 44
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'is a hash with the correct seconds' do
|
97
|
+
chronologicable.duration[:seconds].should eql 23
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'when the chronologicable represents something with an even second time duration' do
|
102
|
+
before { chronologicable.should_receive(:duration_in_seconds).any_number_of_times.and_return(6240) }
|
103
|
+
|
104
|
+
it 'is a hash with the correct hours' do
|
105
|
+
chronologicable.duration[:hours].should eql 1
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'is a hash with the correct minutes' do
|
109
|
+
chronologicable.duration[:minutes].should eql 44
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'is a hash with the correct seconds' do
|
113
|
+
chronologicable.duration[:seconds].should eql 0
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'when the chronologicable represents something with an even minute time duration' do
|
118
|
+
before { chronologicable.should_receive(:duration_in_seconds).any_number_of_times.and_return(3600) }
|
119
|
+
|
120
|
+
it 'is a hash with the correct hours' do
|
121
|
+
chronologicable.duration[:hours].should eql 1
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'is a hash with the correct minutes' do
|
125
|
+
chronologicable.duration[:minutes].should eql 0
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'is a hash with the correct seconds' do
|
129
|
+
chronologicable.duration[:seconds].should eql 0
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'when the chronologicable represents something with a zero duration' do
|
134
|
+
before { chronologicable.should_receive(:duration_in_seconds).any_number_of_times.and_return(0) }
|
135
|
+
|
136
|
+
it 'is a hash with the correct hours' do
|
137
|
+
chronologicable.duration[:hours].should eql 0
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'is a hash with the correct minutes' do
|
141
|
+
chronologicable.duration[:minutes].should eql 0
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'is a hash with the correct seconds' do
|
145
|
+
chronologicable.duration[:seconds].should eql 0
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'when duration in seconds returns an empty value' do
|
150
|
+
before { chronologicable.should_receive(:duration_in_seconds).and_return(nil) }
|
151
|
+
|
152
|
+
it 'is an empty hash' do
|
153
|
+
chronologicable.duration.should eql Hash.new
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '#in_progress?', :timecop => true do
|
159
|
+
let(:later) { Time.local(2012, 7, 26, 6, 0, 26) }
|
160
|
+
let(:now) { Time.local(2012, 7, 26, 6, 0, 25) }
|
161
|
+
let(:past) { Time.local(2012, 7, 26, 6, 0, 24) }
|
162
|
+
|
163
|
+
before { Timecop.freeze(now) }
|
164
|
+
|
165
|
+
context 'when it does not have an absolute timeframe' do
|
166
|
+
before { chronologicable.should_receive(:has_absolute_timeframe?).and_return(false) }
|
167
|
+
|
168
|
+
it 'is false' do
|
169
|
+
chronologicable.should_not be_in_progress
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'when it has already started' do
|
174
|
+
let(:started_at) { past }
|
175
|
+
|
176
|
+
context 'and already ended' do
|
177
|
+
let(:ended_at) { past }
|
178
|
+
|
179
|
+
it 'is false' do
|
180
|
+
chronologicable.should_not be_in_progress
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'and ends now' do
|
185
|
+
let(:ended_at) { now }
|
186
|
+
|
187
|
+
it 'is false' do
|
188
|
+
chronologicable.should_not be_in_progress
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'and ends later' do
|
193
|
+
let(:ended_at) { later }
|
194
|
+
|
195
|
+
it 'is true' do
|
196
|
+
chronologicable.should be_in_progress
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'when there is a chronologicable that starts now' do
|
202
|
+
let(:started_at) { now }
|
203
|
+
|
204
|
+
context 'and ends now' do
|
205
|
+
let(:ended_at) { now }
|
206
|
+
|
207
|
+
it 'is false' do
|
208
|
+
chronologicable.should_not be_in_progress
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context 'and ends later' do
|
213
|
+
let(:ended_at) { later }
|
214
|
+
|
215
|
+
it 'is true' do
|
216
|
+
chronologicable.should be_in_progress
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context 'when there is a chronologicable that has not yet started' do
|
222
|
+
let(:started_at) { later }
|
223
|
+
let(:ended_at) { later }
|
224
|
+
|
225
|
+
it 'is false' do
|
226
|
+
chronologicable.should_not be_in_progress
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class RelativeChronologicable < ActiveRecord::Base
|
4
|
+
include Chronological::RelativeTimeframe
|
5
|
+
|
6
|
+
relative_timeframe :start => :starting_offset,
|
7
|
+
:end => :ending_offset,
|
8
|
+
:base_utc => :base_datetime_utc
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Chronological::RelativeTimeframe do
|
12
|
+
let(:now) { Time.local(2012, 7, 26, 6, 0, 0) }
|
13
|
+
let(:base_time) { Time.local(2012, 7, 26, 6, 0, 30) }
|
14
|
+
|
15
|
+
before { Timecop.freeze(now) }
|
16
|
+
|
17
|
+
let(:chronologicable) do
|
18
|
+
RelativeChronologicable.create(
|
19
|
+
:starting_offset => starting_offset,
|
20
|
+
:ending_offset => ending_offset,
|
21
|
+
:base_datetime_utc => base_time)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#started_at_utc' do
|
25
|
+
let(:ending_offset) { 'anything' }
|
26
|
+
|
27
|
+
context 'when the starting offset is set' do
|
28
|
+
let(:starting_offset) { 30 }
|
29
|
+
|
30
|
+
context 'but the base time is not set' do
|
31
|
+
let(:base_time) { nil }
|
32
|
+
|
33
|
+
it 'is nil' do
|
34
|
+
chronologicable.started_at_utc.should be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'and the base time is set' do
|
39
|
+
let(:base_time) { Time.local(2012, 7, 26, 6, 0, 30) }
|
40
|
+
|
41
|
+
it 'is the proper offset calculation' do
|
42
|
+
chronologicable.started_at_utc.should eql Time.local(2012, 7, 26, 6, 0, 0)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when the starting offset is not set' do
|
48
|
+
let(:starting_offset) { nil }
|
49
|
+
|
50
|
+
it 'is nil' do
|
51
|
+
chronologicable.started_at_utc.should be_nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#ended_at_utc' do
|
57
|
+
let(:starting_offset) { 'anything' }
|
58
|
+
|
59
|
+
context 'when the ending offset is set' do
|
60
|
+
let(:ending_offset) { 30 }
|
61
|
+
|
62
|
+
context 'but the base time is not set' do
|
63
|
+
let(:base_time) { nil }
|
64
|
+
|
65
|
+
it 'is nil' do
|
66
|
+
chronologicable.ended_at_utc.should be_nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'and the base time is set' do
|
71
|
+
let(:base_time) { Time.local(2012, 7, 26, 6, 0, 30) }
|
72
|
+
|
73
|
+
it 'is the proper offset calculation' do
|
74
|
+
chronologicable.ended_at_utc.should eql Time.local(2012, 7, 26, 6, 0, 0)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when the ending offset is not set' do
|
80
|
+
let(:ending_offset) { nil }
|
81
|
+
|
82
|
+
it 'is nil' do
|
83
|
+
chronologicable.ended_at_utc.should be_nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when the base time is not set' do
|
89
|
+
let(:now) { Time.local(2012, 7, 26, 6, 0, 0) }
|
90
|
+
let(:base_time) { nil }
|
91
|
+
|
92
|
+
context 'but the starting offset is set' do
|
93
|
+
let(:starting_offset) { 30 }
|
94
|
+
|
95
|
+
context 'and the ending offset is set' do
|
96
|
+
let(:ending_offset) { 0 }
|
97
|
+
|
98
|
+
it 'is not scheduled' do
|
99
|
+
chronologicable.should_not be_scheduled
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'is partially scheduled' do
|
103
|
+
chronologicable.should be_partially_scheduled
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'and the ending offset is not set' do
|
108
|
+
let(:ending_offset) { nil }
|
109
|
+
|
110
|
+
it 'is not scheduled' do
|
111
|
+
chronologicable.should_not be_scheduled
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'is partially scheduled' do
|
115
|
+
chronologicable.should be_partially_scheduled
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'and the starting offset is not set' do
|
121
|
+
let(:starting_offset) { nil }
|
122
|
+
|
123
|
+
context 'but the ending offset is set' do
|
124
|
+
let(:ending_offset) { 0 }
|
125
|
+
|
126
|
+
it 'is not scheduled' do
|
127
|
+
chronologicable.should_not be_scheduled
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'is partially scheduled' do
|
131
|
+
chronologicable.should be_partially_scheduled
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'and neither of the offsets is set' do
|
137
|
+
let(:starting_offset) { nil }
|
138
|
+
let(:ending_offset) { nil }
|
139
|
+
|
140
|
+
it 'is not scheduled' do
|
141
|
+
chronologicable.should_not be_scheduled
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'is not partially scheduled' do
|
145
|
+
chronologicable.should_not be_partially_scheduled
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when the starting offset is not set' do
|
151
|
+
let(:now) { Time.local(2012, 7, 26, 6, 0, 0) }
|
152
|
+
let(:starting_offset) { nil }
|
153
|
+
|
154
|
+
context 'and the ending offset is not set' do
|
155
|
+
let(:ending_offset) { nil }
|
156
|
+
|
157
|
+
it 'is not scheduled' do
|
158
|
+
chronologicable.should_not be_scheduled
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'is partially scheduled' do
|
162
|
+
chronologicable.should be_partially_scheduled
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'and the ending offset is set' do
|
167
|
+
let(:ending_offset) { 0 }
|
168
|
+
|
169
|
+
it 'is not scheduled' do
|
170
|
+
chronologicable.should_not be_scheduled
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'is partially scheduled' do
|
174
|
+
chronologicable.should be_partially_scheduled
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'when the starting offset is set' do
|
180
|
+
let(:now) { Time.local(2012, 7, 26, 6, 0, 0) }
|
181
|
+
let(:starting_offset) { 30 }
|
182
|
+
|
183
|
+
context 'and the ending offset is not set' do
|
184
|
+
let(:ending_offset) { nil }
|
185
|
+
|
186
|
+
it 'is not scheduled' do
|
187
|
+
chronologicable.should_not be_scheduled
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'is partially scheduled' do
|
191
|
+
chronologicable.should be_partially_scheduled
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'and the ending offset is set' do
|
196
|
+
let(:ending_offset) { 0 }
|
197
|
+
|
198
|
+
it 'is scheduled' do
|
199
|
+
chronologicable.should be_scheduled
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'is partially scheduled' do
|
203
|
+
chronologicable.should be_partially_scheduled
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -16,7 +16,18 @@ RSpec.configure do |config|
|
|
16
16
|
|
17
17
|
class SetupTests < ActiveRecord::Migration
|
18
18
|
def up
|
19
|
-
create_table :
|
19
|
+
create_table :base_chronologicables do |t|
|
20
|
+
t.datetime :started_at
|
21
|
+
t.datetime :ended_at
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :relative_chronologicables do |t|
|
25
|
+
t.integer :starting_offset
|
26
|
+
t.integer :ending_offset
|
27
|
+
t.datetime :base_datetime_utc
|
28
|
+
end
|
29
|
+
|
30
|
+
create_table :absolute_chronologicables do |t|
|
20
31
|
t.datetime :started_at_utc
|
21
32
|
t.datetime :ended_at_utc
|
22
33
|
end
|
@@ -33,7 +44,9 @@ RSpec.configure do |config|
|
|
33
44
|
end
|
34
45
|
|
35
46
|
config.before(:each) do
|
36
|
-
ActiveRecord::Base.connection.execute 'DELETE FROM
|
47
|
+
ActiveRecord::Base.connection.execute 'DELETE FROM relative_chronologicables'
|
48
|
+
ActiveRecord::Base.connection.execute 'DELETE FROM absolute_chronologicables'
|
49
|
+
ActiveRecord::Base.connection.execute 'DELETE FROM chronologicable_with_time_zones'
|
37
50
|
end
|
38
51
|
|
39
52
|
config.after(:suite) do
|