acts_as_bookable 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +43 -0
- data/Appraisals +21 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +168 -0
- data/Guardfile +5 -0
- data/MIT-LICENSE +20 -0
- data/README.md +473 -0
- data/Rakefile +19 -0
- data/acts_as_bookable.gemspec +41 -0
- data/app/assets/images/acts_as_bookable/.keep +0 -0
- data/app/assets/javascripts/acts_as_bookable/application.js +13 -0
- data/app/assets/stylesheets/acts_as_bookable/application.css +15 -0
- data/app/controllers/acts_as_bookable/application_controller.rb +4 -0
- data/app/helpers/acts_as_bookable/application_helper.rb +4 -0
- data/app/views/layouts/acts_as_bookable/application.html.erb +14 -0
- data/bin/rails +12 -0
- data/config/locales/en.yml +12 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20160217085200_create_acts_as_bookable_bookings.rb +14 -0
- data/gemfiles/activerecord_3.2.gemfile +16 -0
- data/gemfiles/activerecord_4.0.gemfile +16 -0
- data/gemfiles/activerecord_4.1.gemfile +16 -0
- data/gemfiles/activerecord_4.2.gemfile +17 -0
- data/gemfiles/activerecord_5.0.gemfile +17 -0
- data/lib/acts_as_bookable/bookable/core.rb +285 -0
- data/lib/acts_as_bookable/bookable.rb +56 -0
- data/lib/acts_as_bookable/booker.rb +70 -0
- data/lib/acts_as_bookable/booking.rb +54 -0
- data/lib/acts_as_bookable/db_utils.rb +39 -0
- data/lib/acts_as_bookable/engine.rb +5 -0
- data/lib/acts_as_bookable/t.rb +11 -0
- data/lib/acts_as_bookable/time_utils.rb +135 -0
- data/lib/acts_as_bookable/version.rb +3 -0
- data/lib/acts_as_bookable.rb +42 -0
- data/lib/tasks/acts_as_bookable_tasks.rake +4 -0
- data/spec/acts_as_bookable/acts_as_bookable_spec.rb +52 -0
- data/spec/acts_as_bookable/acts_as_booker_spec.rb +57 -0
- data/spec/acts_as_bookable/bookable/core_spec.rb +593 -0
- data/spec/acts_as_bookable/bookable_spec.rb +124 -0
- data/spec/acts_as_bookable/booker_spec.rb +140 -0
- data/spec/acts_as_bookable/booking_spec.rb +241 -0
- data/spec/acts_as_bookable/schedule_spec.rb +137 -0
- data/spec/acts_as_bookable/time_utils_spec.rb +525 -0
- data/spec/factories/bookable.rb +7 -0
- data/spec/factories/booker.rb +5 -0
- data/spec/factories/room.rb +11 -0
- data/spec/internal/app/models/Bookable.rb +3 -0
- data/spec/internal/app/models/Booker.rb +3 -0
- data/spec/internal/app/models/Event.rb +3 -0
- data/spec/internal/app/models/Generic.rb +2 -0
- data/spec/internal/app/models/NotBooker.rb +2 -0
- data/spec/internal/app/models/Room.rb +3 -0
- data/spec/internal/app/models/Show.rb +3 -0
- data/spec/internal/app/models/Unbookable.rb +2 -0
- data/spec/internal/config/database.yml.sample +17 -0
- data/spec/internal/db/schema.rb +51 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/0-helpers.rb +32 -0
- data/spec/support/1-database.rb +42 -0
- data/spec/support/2-database_cleaner.rb +21 -0
- data/spec/support/3-factory_girl.rb +12 -0
- metadata +296 -0
@@ -0,0 +1,525 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'ActsAsBookable::TimeUtils' do
|
4
|
+
|
5
|
+
describe '#time_in_interval?' do
|
6
|
+
before :each do
|
7
|
+
@interval_start = Time.now
|
8
|
+
@interval_end = Time.now + 1.hour
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'returns true' do
|
12
|
+
it 'when time is the interval_start' do
|
13
|
+
time = @interval_start
|
14
|
+
expect(ActsAsBookable::TimeUtils.time_in_interval?(time,@interval_start,@interval_end)).to eq true
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'when time is bewteen interval_start and interval_end' do
|
18
|
+
time = @interval_start + 5.minutes
|
19
|
+
expect(ActsAsBookable::TimeUtils.time_in_interval?(time,@interval_start,@interval_end)).to eq true
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'when time is very close to interval end' do
|
23
|
+
time = @interval_end - 1.second
|
24
|
+
expect(ActsAsBookable::TimeUtils.time_in_interval?(time,@interval_start,@interval_end)).to eq true
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'returns false' do
|
30
|
+
it 'when time is before interval_start' do
|
31
|
+
time = @interval_start - 1.second
|
32
|
+
expect(ActsAsBookable::TimeUtils.time_in_interval?(time,@interval_start,@interval_end)).to eq false
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'when time is after interval_end' do
|
36
|
+
time = @interval_end + 1.second
|
37
|
+
expect(ActsAsBookable::TimeUtils.time_in_interval?(time,@interval_start,@interval_end)).to eq false
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'when time is interval_end' do
|
41
|
+
time = @interval_end
|
42
|
+
expect(ActsAsBookable::TimeUtils.time_in_interval?(time,@interval_start,@interval_end)).to eq false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#interval_in_schedule?' do
|
48
|
+
before :each do
|
49
|
+
@day0 = '2016-01-05'.to_date
|
50
|
+
@schedule = IceCube::Schedule.new(@day0,duration: 1.day)
|
51
|
+
@schedule.add_recurrence_rule IceCube::Rule.monthly.day_of_month(1,3,5,7)
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'returns true' do
|
55
|
+
it 'when range starts and ends in the middle of an occurrence' do
|
56
|
+
time_start = @day0 + 1.hour
|
57
|
+
time_end = @day0 + 3.hours
|
58
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq true
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'when range starts and ends in the middle of another occurrence' do
|
62
|
+
time_start = @day0 + 2.days + 1.hour
|
63
|
+
time_end = @day0 + 2.days + 3.hours
|
64
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq true
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'when range starts at the beginning of an occurrence and ends at the end of the same occurence' do
|
68
|
+
time_start = @day0
|
69
|
+
time_end = @day0 + 1.day - 1.second
|
70
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'retuns false' do
|
75
|
+
it 'when range starts and ends outside any occurrence' do
|
76
|
+
time_start = '2016-01-15'.to_date
|
77
|
+
time_end = time_start + 1.day
|
78
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq false
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'when range starts and ends outside any occurrence but contains an occurrence' do
|
82
|
+
time_start = @day0 - 1.hour
|
83
|
+
time_end = @day0 + 1.day + 1.hour
|
84
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq false
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'when range starts within an occurrence but ends outside it' do
|
88
|
+
time_start = @day0 + 1.hour
|
89
|
+
time_end = @day0 + 1.day + 1.hour
|
90
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq false
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'when range starts outside any occurrence but ends within an occurrence' do
|
94
|
+
time_start = @day0 - 1.hour
|
95
|
+
time_end = @day0 + 1.hour
|
96
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq false
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'when range starts within an occurrence and ends within a different occurrence' do
|
100
|
+
time_start = @day0 + 1.hour
|
101
|
+
time_end = @day0 + 2.days + 1.hour
|
102
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq false
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'when range starts within an occurrence and ends just after the end of the same occurrence' do
|
106
|
+
time_start = @day0 + 1.hour
|
107
|
+
time_end = @day0 + 1.day
|
108
|
+
expect(ActsAsBookable::TimeUtils.interval_in_schedule?(@schedule,time_start,time_end)).to eq false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#time_in_schedule?' do
|
114
|
+
before :each do
|
115
|
+
@day0 = '2016-01-05'.to_date
|
116
|
+
@schedule = IceCube::Schedule.new(@day0,duration: 1.day)
|
117
|
+
@schedule.add_recurrence_rule IceCube::Rule.monthly.day_of_month(1,3,5,7)
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'returns true' do
|
121
|
+
it 'when time is at the beginning of an occurrence' do
|
122
|
+
time = @day0
|
123
|
+
expect(ActsAsBookable::TimeUtils.time_in_schedule?(@schedule,time)).to eq true
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'when time is in the middle of an occurrence' do
|
127
|
+
time = @day0 + 5.hours
|
128
|
+
expect(ActsAsBookable::TimeUtils.time_in_schedule?(@schedule,time)).to eq true
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'when time is at the end of an occurrence' do
|
132
|
+
time = @day0 + 1.day - 1.second
|
133
|
+
expect(ActsAsBookable::TimeUtils.time_in_schedule?(@schedule, time)).to eq true
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'retuns false' do
|
138
|
+
it 'when time is outside an occurrence' do
|
139
|
+
time = '2016-01-15'.to_date
|
140
|
+
expect(ActsAsBookable::TimeUtils.time_in_schedule?(@schedule, time)).to eq false
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'when time is close to the end of an occurrence, but outside it' do
|
144
|
+
time = @day0 + 1.day
|
145
|
+
expect(ActsAsBookable::TimeUtils.time_in_schedule?(@schedule, time)).to eq false
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'when time is close to the beginning of an occurrence, but outside it' do
|
149
|
+
time = @day0 + 2.days - 1.second
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#subintervals' do
|
155
|
+
before :each do
|
156
|
+
@time = Time.now
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'returns ArgumentError if called without an array' do
|
160
|
+
expect{ ActsAsBookable::TimeUtils.subintervals(1) }.to raise_error ArgumentError
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'returns ArgumentError if an interval has no time_start or time_end' do
|
164
|
+
intervals = [
|
165
|
+
{time_start: @time, time_end: @time + 1.hour},
|
166
|
+
{time_start: @time}
|
167
|
+
]
|
168
|
+
expect{ ActsAsBookable::TimeUtils.subintervals(1) }.to raise_error ArgumentError
|
169
|
+
intervals = [
|
170
|
+
{time_start: @time, time_end: @time + 1.hour},
|
171
|
+
{time_end: @time}
|
172
|
+
]
|
173
|
+
expect{ ActsAsBookable::TimeUtils.subintervals(1) }.to raise_error ArgumentError
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'returns ArgumentError if time_start or time_end is not a Time or Date' do
|
177
|
+
intervals = [
|
178
|
+
{time_start: @time, time_end: 1}
|
179
|
+
]
|
180
|
+
expect{ ActsAsBookable::TimeUtils.subintervals(1) }.to raise_error ArgumentError
|
181
|
+
intervals = [
|
182
|
+
{time_start: 2, time_end: @time + 1.hour}
|
183
|
+
]
|
184
|
+
expect{ ActsAsBookable::TimeUtils.subintervals(1) }.to raise_error ArgumentError
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'returns empty array if input is an empty array' do
|
188
|
+
expect(ActsAsBookable::TimeUtils.subintervals([])).to eq []
|
189
|
+
end
|
190
|
+
|
191
|
+
# |----|
|
192
|
+
# =>
|
193
|
+
# |----|
|
194
|
+
it 'returns a copy of the same interval if input is a single interval' do
|
195
|
+
intervals = [
|
196
|
+
{time_start: @time, time_end: @time + 1.hour}
|
197
|
+
]
|
198
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals)
|
199
|
+
expect(subintervals.length).to eq 1
|
200
|
+
expect(subintervals[0][:time_start]).to eq intervals[0][:time_start]
|
201
|
+
expect(subintervals[0][:time_end]).to eq intervals[0][:time_end]
|
202
|
+
end
|
203
|
+
|
204
|
+
# |----| |----| |----|
|
205
|
+
# =>
|
206
|
+
# |----| |----| |----|
|
207
|
+
it 'returns a copy of the same intervals if they are all separated' do
|
208
|
+
intervals = [
|
209
|
+
{time_start: @time, time_end: @time + 1.hour},
|
210
|
+
{time_start: @time + 2.hours, time_end: @time + 3.hours},
|
211
|
+
{time_start: @time + 4.hours, time_end: @time + 5.hours}
|
212
|
+
]
|
213
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals)
|
214
|
+
expect(subintervals.length).to eq 3
|
215
|
+
(0..2).each do |i|
|
216
|
+
expect(subintervals[i][:time_start]).to eq intervals[i][:time_start]
|
217
|
+
expect(subintervals[i][:time_end]).to eq intervals[i][:time_end]
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# |----|
|
222
|
+
# |----|
|
223
|
+
# |----|
|
224
|
+
# =>
|
225
|
+
# |----|
|
226
|
+
# |----|
|
227
|
+
# |----|
|
228
|
+
it 'returns the sub-intervals sorted' do
|
229
|
+
time0 = @time
|
230
|
+
time1 = @time + 1.hour
|
231
|
+
time2 = @time + 2.hours
|
232
|
+
time3 = @time + 3.hours
|
233
|
+
time4 = @time + 4.hours
|
234
|
+
time5 = @time + 5.hours
|
235
|
+
time6 = @time + 6.hours
|
236
|
+
|
237
|
+
intervals = [
|
238
|
+
{time_start: time4, time_end: time5},
|
239
|
+
{time_start: time2, time_end: time3},
|
240
|
+
{time_start: time0, time_end: time1}
|
241
|
+
]
|
242
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals)
|
243
|
+
expect(subintervals.length).to eq 3
|
244
|
+
expect(subintervals[0][:time_start]).to eq time0
|
245
|
+
expect(subintervals[0][:time_end]).to eq time1
|
246
|
+
expect(subintervals[1][:time_start]).to eq time2
|
247
|
+
expect(subintervals[1][:time_end]).to eq time3
|
248
|
+
expect(subintervals[2][:time_start]).to eq time4
|
249
|
+
expect(subintervals[2][:time_end]).to eq time5
|
250
|
+
end
|
251
|
+
|
252
|
+
# |----|
|
253
|
+
# |----|
|
254
|
+
# |----|
|
255
|
+
# =>
|
256
|
+
# |----|
|
257
|
+
it 'merges intervals if they have same time_start and time_end' do
|
258
|
+
intervals = [
|
259
|
+
{time_start: @time, time_end: @time + 1.hour},
|
260
|
+
{time_start: @time, time_end: @time + 1.hour},
|
261
|
+
{time_start: @time, time_end: @time + 1.hour}
|
262
|
+
]
|
263
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals)
|
264
|
+
expect(subintervals.length).to eq 1
|
265
|
+
expect(subintervals[0][:time_start]).to eq intervals[0][:time_start]
|
266
|
+
expect(subintervals[0][:time_end]).to eq intervals[0][:time_end]
|
267
|
+
end
|
268
|
+
|
269
|
+
# |---|
|
270
|
+
# |------|
|
271
|
+
# =>
|
272
|
+
# |---|
|
273
|
+
# |--|
|
274
|
+
it 'returns two intervals if input is 2 intervals with same time_start and different time_end' do
|
275
|
+
time0 = @time
|
276
|
+
time1 = @time + 1.hour
|
277
|
+
time2 = @time + 2.hours
|
278
|
+
intervals = [
|
279
|
+
{time_start: time0, time_end: time1},
|
280
|
+
{time_start: time0, time_end: time2}
|
281
|
+
]
|
282
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals)
|
283
|
+
expect(subintervals.length).to eq 2
|
284
|
+
expect(subintervals[0][:time_start]).to eq time0
|
285
|
+
expect(subintervals[0][:time_end]).to eq time1
|
286
|
+
expect(subintervals[1][:time_start]).to eq time1
|
287
|
+
expect(subintervals[1][:time_end]).to eq time2
|
288
|
+
end
|
289
|
+
|
290
|
+
# |------|
|
291
|
+
# |---|
|
292
|
+
# =>
|
293
|
+
# |--|
|
294
|
+
# |---|
|
295
|
+
it 'returns two intervals if input is 2 intervals with same time_end and different time_start' do
|
296
|
+
time0 = @time
|
297
|
+
time1 = @time + 1.hour
|
298
|
+
time2 = @time + 2.hours
|
299
|
+
intervals = [
|
300
|
+
{time_start: time0, time_end: time2},
|
301
|
+
{time_start: time1, time_end: time2}
|
302
|
+
]
|
303
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals)
|
304
|
+
expect(subintervals.length).to eq 2
|
305
|
+
expect(subintervals[0][:time_start]).to eq time0
|
306
|
+
expect(subintervals[0][:time_end]).to eq time1
|
307
|
+
expect(subintervals[1][:time_start]).to eq time1
|
308
|
+
expect(subintervals[1][:time_end]).to eq time2
|
309
|
+
end
|
310
|
+
|
311
|
+
# |---------|
|
312
|
+
# |---|
|
313
|
+
# =>
|
314
|
+
# |--|
|
315
|
+
# |---|
|
316
|
+
# |--|
|
317
|
+
it 'returns three intervals if one includes another' do
|
318
|
+
time0 = @time
|
319
|
+
time1 = @time + 1.hour
|
320
|
+
time2 = @time + 2.hours
|
321
|
+
time3 = @time + 3.hours
|
322
|
+
intervals = [
|
323
|
+
{time_start: time0, time_end: time3},
|
324
|
+
{time_start: time1, time_end: time2}
|
325
|
+
]
|
326
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals)
|
327
|
+
expect(subintervals.length).to eq 3
|
328
|
+
expect(subintervals[0][:time_start]).to eq time0
|
329
|
+
expect(subintervals[0][:time_end]).to eq time1
|
330
|
+
expect(subintervals[1][:time_start]).to eq time1
|
331
|
+
expect(subintervals[1][:time_end]).to eq time2
|
332
|
+
expect(subintervals[2][:time_start]).to eq time2
|
333
|
+
expect(subintervals[2][:time_end]).to eq time3
|
334
|
+
end
|
335
|
+
|
336
|
+
# |---2---|
|
337
|
+
# |------4------|
|
338
|
+
# |----3------|
|
339
|
+
# |----1----|
|
340
|
+
# |----8----|
|
341
|
+
# =>
|
342
|
+
# |-5-|
|
343
|
+
# |-9-|
|
344
|
+
# |-7-|
|
345
|
+
# |--4--|
|
346
|
+
# |----9----|
|
347
|
+
it 'correctly merges interval attributes' do
|
348
|
+
time0 = @time
|
349
|
+
time1 = @time + 1.hour
|
350
|
+
time2 = @time + 2.hours
|
351
|
+
time3 = @time + 3.hours
|
352
|
+
time4 = @time + 4.hours
|
353
|
+
time5 = @time + 5.hours
|
354
|
+
time6 = @time + 6.hours
|
355
|
+
intervals = [
|
356
|
+
{time_start: time0, time_end: time2, attr: 2},
|
357
|
+
{time_start: time1, time_end: time4, attr: 4},
|
358
|
+
{time_start: time0, time_end: time3, attr: 3},
|
359
|
+
{time_start: time5, time_end: time6, attr: 1},
|
360
|
+
{time_start: time5, time_end: time6, attr: 8}
|
361
|
+
]
|
362
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals) do |a,b,op|
|
363
|
+
if op == :open
|
364
|
+
res = {attr: a[:attr] + b[:attr]}
|
365
|
+
end
|
366
|
+
if op == :close
|
367
|
+
res = {attr: a[:attr] - b[:attr]}
|
368
|
+
end
|
369
|
+
res
|
370
|
+
end
|
371
|
+
expect(subintervals.length).to eq 5
|
372
|
+
expect(subintervals[0][:time_start]).to eq time0
|
373
|
+
expect(subintervals[0][:time_end]).to eq time1
|
374
|
+
expect(subintervals[0][:attr]).to eq 5
|
375
|
+
expect(subintervals[1][:time_start]).to eq time1
|
376
|
+
expect(subintervals[1][:time_end]).to eq time2
|
377
|
+
expect(subintervals[1][:attr]).to eq 9
|
378
|
+
expect(subintervals[2][:time_start]).to eq time2
|
379
|
+
expect(subintervals[2][:time_end]).to eq time3
|
380
|
+
expect(subintervals[2][:attr]).to eq 7
|
381
|
+
expect(subintervals[3][:time_start]).to eq time3
|
382
|
+
expect(subintervals[3][:time_end]).to eq time4
|
383
|
+
expect(subintervals[3][:attr]).to eq 4
|
384
|
+
expect(subintervals[4][:time_start]).to eq time5
|
385
|
+
expect(subintervals[4][:time_end]).to eq time6
|
386
|
+
expect(subintervals[4][:attr]).to eq 9
|
387
|
+
end
|
388
|
+
|
389
|
+
# |---2---|
|
390
|
+
# |------4------|
|
391
|
+
# |----3------|
|
392
|
+
# |----1----|
|
393
|
+
# |----8----|
|
394
|
+
# =>
|
395
|
+
# |-5-|
|
396
|
+
# |-9-|
|
397
|
+
# |-7-|
|
398
|
+
# |--4--|
|
399
|
+
# |----9----|
|
400
|
+
it 'correctly merges interval attributes handling dates and times' do
|
401
|
+
time0 = Date.today
|
402
|
+
time1 = time0 + 1
|
403
|
+
time2 = time0 + 2
|
404
|
+
time3 = time0 + 3
|
405
|
+
time4 = time0 + 4.days + 1.hours
|
406
|
+
time5 = time0 + 5.days + 1.hours
|
407
|
+
time6 = time0 + 6.days + 1.hours
|
408
|
+
intervals = [
|
409
|
+
{time_start: time0, time_end: time2, attr: 2},
|
410
|
+
{time_start: time1, time_end: time4, attr: 4},
|
411
|
+
{time_start: time0, time_end: time3, attr: 3},
|
412
|
+
{time_start: time5, time_end: time6, attr: 1},
|
413
|
+
{time_start: time5, time_end: time6, attr: 8}
|
414
|
+
]
|
415
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals) do |a,b,op|
|
416
|
+
if op == :open
|
417
|
+
res = {attr: a[:attr] + b[:attr]}
|
418
|
+
end
|
419
|
+
if op == :close
|
420
|
+
res = {attr: a[:attr] - b[:attr]}
|
421
|
+
end
|
422
|
+
res
|
423
|
+
end
|
424
|
+
expect(subintervals.length).to eq 5
|
425
|
+
expect(subintervals[0][:time_start]).to eq time0
|
426
|
+
expect(subintervals[0][:time_end]).to eq time1
|
427
|
+
expect(subintervals[0][:attr]).to eq 5
|
428
|
+
expect(subintervals[1][:time_start]).to eq time1
|
429
|
+
expect(subintervals[1][:time_end]).to eq time2
|
430
|
+
expect(subintervals[1][:attr]).to eq 9
|
431
|
+
expect(subintervals[2][:time_start]).to eq time2
|
432
|
+
expect(subintervals[2][:time_end]).to eq time3
|
433
|
+
expect(subintervals[2][:attr]).to eq 7
|
434
|
+
expect(subintervals[3][:time_start]).to eq time3
|
435
|
+
expect(subintervals[3][:time_end]).to eq time4
|
436
|
+
expect(subintervals[3][:attr]).to eq 4
|
437
|
+
expect(subintervals[4][:time_start]).to eq time5
|
438
|
+
expect(subintervals[4][:time_end]).to eq time6
|
439
|
+
expect(subintervals[4][:attr]).to eq 9
|
440
|
+
end
|
441
|
+
|
442
|
+
# |---2---|
|
443
|
+
# |---4---|
|
444
|
+
# |---3---|
|
445
|
+
# |---5---|
|
446
|
+
# |---1---|
|
447
|
+
# |---1---|
|
448
|
+
# =>
|
449
|
+
# |---6---|
|
450
|
+
# |---10---|
|
451
|
+
it 'merges 3 intervals partially matching' do
|
452
|
+
time0 = @time
|
453
|
+
time1 = @time + 1.hour
|
454
|
+
time2 = @time + 2.hours
|
455
|
+
intervals = [
|
456
|
+
{time_start: time0, time_end: time1, attr: 2},
|
457
|
+
{time_start: time1, time_end: time2, attr: 4},
|
458
|
+
{time_start: time0, time_end: time1, attr: 3},
|
459
|
+
{time_start: time1, time_end: time2, attr: 5},
|
460
|
+
{time_start: time0, time_end: time1, attr: 1},
|
461
|
+
{time_start: time1, time_end: time2, attr: 1}
|
462
|
+
]
|
463
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals) do |a,b,op|
|
464
|
+
if op == :open
|
465
|
+
res = {attr: a[:attr] + b[:attr]}
|
466
|
+
end
|
467
|
+
if op == :close
|
468
|
+
res = {attr: a[:attr] - b[:attr]}
|
469
|
+
end
|
470
|
+
res
|
471
|
+
end
|
472
|
+
expect(subintervals.length).to eq 2
|
473
|
+
expect(subintervals[0][:time_start]).to eq time0
|
474
|
+
expect(subintervals[0][:time_end]).to eq time1
|
475
|
+
expect(subintervals[0][:attr]).to eq 6
|
476
|
+
expect(subintervals[1][:time_start]).to eq time1
|
477
|
+
expect(subintervals[1][:time_end]).to eq time2
|
478
|
+
expect(subintervals[1][:attr]).to eq 10
|
479
|
+
end
|
480
|
+
|
481
|
+
# |---2----|
|
482
|
+
# |----4---|
|
483
|
+
# |---3----|
|
484
|
+
# |----5---|
|
485
|
+
# |---1----|
|
486
|
+
# |----1---|
|
487
|
+
# =>
|
488
|
+
# |-6-|
|
489
|
+
# |-16-|
|
490
|
+
# |-10-|
|
491
|
+
it 'merges and split 3 intervals partially matching' do
|
492
|
+
time0 = @time
|
493
|
+
time1 = @time + 1.hour
|
494
|
+
time2 = @time + 2.hours
|
495
|
+
time3 = @time + 3.hours
|
496
|
+
intervals = [
|
497
|
+
{time_start: time0, time_end: time2, attr: 2},
|
498
|
+
{time_start: time1, time_end: time3, attr: 4},
|
499
|
+
{time_start: time0, time_end: time2, attr: 3},
|
500
|
+
{time_start: time1, time_end: time3, attr: 5},
|
501
|
+
{time_start: time0, time_end: time2, attr: 1},
|
502
|
+
{time_start: time1, time_end: time3, attr: 1}
|
503
|
+
]
|
504
|
+
subintervals = ActsAsBookable::TimeUtils.subintervals(intervals) do |a,b,op|
|
505
|
+
if op == :open
|
506
|
+
res = {attr: a[:attr] + b[:attr]}
|
507
|
+
end
|
508
|
+
if op == :close
|
509
|
+
res = {attr: a[:attr] - b[:attr]}
|
510
|
+
end
|
511
|
+
res
|
512
|
+
end
|
513
|
+
expect(subintervals.length).to eq 3
|
514
|
+
expect(subintervals[0][:time_start]).to eq time0
|
515
|
+
expect(subintervals[0][:time_end]).to eq time1
|
516
|
+
expect(subintervals[0][:attr]).to eq 6
|
517
|
+
expect(subintervals[1][:time_start]).to eq time1
|
518
|
+
expect(subintervals[1][:time_end]).to eq time2
|
519
|
+
expect(subintervals[1][:attr]).to eq 16
|
520
|
+
expect(subintervals[2][:time_start]).to eq time2
|
521
|
+
expect(subintervals[2][:time_end]).to eq time3
|
522
|
+
expect(subintervals[2][:attr]).to eq 10
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
sqlite3:
|
2
|
+
adapter: sqlite3
|
3
|
+
database: ':memory:'
|
4
|
+
|
5
|
+
mysql:
|
6
|
+
adapter: mysql2
|
7
|
+
host: localhost
|
8
|
+
username: root
|
9
|
+
database: acts_as_bookable
|
10
|
+
charset: utf8
|
11
|
+
|
12
|
+
postgresql:
|
13
|
+
adapter: postgresql
|
14
|
+
hostname: localhost
|
15
|
+
username: postgres
|
16
|
+
database: acts_as_bookable
|
17
|
+
encoding: utf8
|
@@ -0,0 +1,51 @@
|
|
1
|
+
ActiveRecord::Schema.define version: 0 do
|
2
|
+
create_table :acts_as_bookable_bookings, force: true do |t|
|
3
|
+
t.references :bookable, polymorphic: true
|
4
|
+
t.references :booker, polymorphic: true
|
5
|
+
t.column :amount, :integer
|
6
|
+
t.column :schedule, :text
|
7
|
+
t.column :time_start, :datetime
|
8
|
+
t.column :time_end, :datetime
|
9
|
+
t.column :time, :datetime
|
10
|
+
t.datetime :created_at
|
11
|
+
end
|
12
|
+
|
13
|
+
create_table :bookables, force: true do |t|
|
14
|
+
t.column :name, :string
|
15
|
+
t.column :schedule, :text
|
16
|
+
t.column :capacity, :integer
|
17
|
+
end
|
18
|
+
|
19
|
+
create_table :rooms, force: true do |t|
|
20
|
+
t.column :name, :string
|
21
|
+
t.column :schedule, :text
|
22
|
+
t.column :capacity, :integer
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table :events, force: true do |t|
|
26
|
+
t.column :name, :string
|
27
|
+
t.column :capacity, :integer
|
28
|
+
end
|
29
|
+
|
30
|
+
create_table :shows, force: true do |t|
|
31
|
+
t.column :name, :string
|
32
|
+
t.column :schedule, :text
|
33
|
+
t.column :capacity, :integer
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :unbookables, force: true do |t|
|
37
|
+
t.column :name, :string
|
38
|
+
end
|
39
|
+
|
40
|
+
create_table :not_bookers, force: true do |t|
|
41
|
+
t.column :name, :string
|
42
|
+
end
|
43
|
+
|
44
|
+
create_table :generics, force: true do |t|
|
45
|
+
t.column :name, :string
|
46
|
+
end
|
47
|
+
|
48
|
+
create_table :bookers, force: true do |t|
|
49
|
+
t.column :name, :string
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
begin
|
2
|
+
require 'pry-nav'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
$LOAD_PATH << '.' unless $LOAD_PATH.include?('.')
|
6
|
+
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
7
|
+
require 'logger'
|
8
|
+
|
9
|
+
require File.expand_path('../../lib/acts_as_bookable', __FILE__)
|
10
|
+
I18n.enforce_available_locales = true
|
11
|
+
require 'rails'
|
12
|
+
require 'barrier'
|
13
|
+
require 'database_cleaner'
|
14
|
+
require 'factory_girl_rails'
|
15
|
+
require 'awesome_print'
|
16
|
+
|
17
|
+
ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../')
|
18
|
+
Dir[File.join(ENGINE_RAILS_ROOT, "spec/factories/**/*.rb")].each {|f| require f }
|
19
|
+
|
20
|
+
Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
|
21
|
+
|
22
|
+
I18n.load_path << File.expand_path("../../config/locales/en.yml", __FILE__)
|
23
|
+
|
24
|
+
RSpec.configure do |config|
|
25
|
+
config.raise_errors_for_deprecations!
|
26
|
+
end
|