schron 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/schron/archive.rb +7 -6
- data/lib/schron/datastore/interface.rb +1 -1
- data/lib/schron/datastore/memory.rb +6 -2
- data/lib/schron/datastore/mongo.rb +20 -4
- data/lib/schron/datastore/sequel.rb +15 -6
- data/lib/schron/datastore/serializer.rb +2 -1
- data/lib/schron/generic_archive.rb +10 -0
- data/lib/schron/generic_entity.rb +18 -0
- data/lib/schron/query.rb +19 -6
- data/lib/schron/test/archive_examples.rb +1 -1
- data/lib/schron/test/datastore_examples.rb +178 -24
- data/schron.gemspec +1 -1
- data/spec/lib/schron/query_spec.rb +20 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7769c035395e049f20cbede7cda51f0b39c8ed28
|
4
|
+
data.tar.gz: 6eacb27127b5d4770d36dd17692697b1bd39d93e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2f2c532a880389220906e087c45772d8430159ff4b102c33aa770793ba1c0e52e7db0714cfb6e3833c3a463e9aa3b273950d362d1e490b58d5600565280fe62
|
7
|
+
data.tar.gz: a3becfbd86f34a23e6a5d3038f35df103ce72cadb31753fbacae795574644987488a9fd8c83693a92fc458f2bc04a78dfc344e116a857ceeee283408b40babca
|
data/lib/schron/archive.rb
CHANGED
@@ -25,14 +25,15 @@ module Schron
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def query(&block)
|
28
|
-
|
28
|
+
Query.new(self, &block)
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
32
|
-
query
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
def all
|
32
|
+
query.all
|
33
|
+
end
|
34
|
+
|
35
|
+
def first
|
36
|
+
query.first
|
36
37
|
end
|
37
38
|
|
38
39
|
def get(id)
|
@@ -50,7 +50,7 @@ module Schron
|
|
50
50
|
def protect_reset
|
51
51
|
unless ENV['SCHRON_RESET']
|
52
52
|
raise Schron::OperationDisabledError,
|
53
|
-
"Can not reset datastore
|
53
|
+
"Can not reset datastore without setting ENV['SCHRON_RESET'] to 1"
|
54
54
|
end
|
55
55
|
yield
|
56
56
|
end
|
@@ -10,13 +10,17 @@ module Schron
|
|
10
10
|
@data = {}
|
11
11
|
end
|
12
12
|
|
13
|
-
def exec_query(
|
14
|
-
results = data_for_kind(kind).values
|
13
|
+
def exec_query(query)
|
14
|
+
results = data_for_kind(query.kind).values
|
15
15
|
results = apply_filters(query, results)
|
16
16
|
results = apply_sorts(query, results)
|
17
17
|
apply_limit_offset(query, results) || []
|
18
18
|
end
|
19
19
|
|
20
|
+
def exec_count(query)
|
21
|
+
exec_query(query).count
|
22
|
+
end
|
23
|
+
|
20
24
|
def multi_get(kind, ids)
|
21
25
|
ids.map { |id| get_data(kind, id) }.compact
|
22
26
|
end
|
@@ -6,15 +6,19 @@ require 'schron/datastore/serializer'
|
|
6
6
|
|
7
7
|
module Schron
|
8
8
|
module Datastore
|
9
|
+
class EmptyQueryError < StandardError
|
10
|
+
end
|
9
11
|
class Mongo
|
10
12
|
include Schron::Datastore::Interface
|
11
13
|
|
14
|
+
attr_reader :db
|
15
|
+
|
12
16
|
def initialize(db)
|
13
17
|
@db = db
|
14
18
|
end
|
15
19
|
|
16
20
|
def get(kind, id)
|
17
|
-
doc = coll(kind).
|
21
|
+
doc = coll(kind).find_one(id_selector(id))
|
18
22
|
doc ?
|
19
23
|
unserialize(kind, doc) :
|
20
24
|
nil
|
@@ -65,11 +69,22 @@ module Schron
|
|
65
69
|
nil
|
66
70
|
end
|
67
71
|
|
68
|
-
def exec_query(
|
72
|
+
def exec_query(query)
|
69
73
|
selector = selector_for(query)
|
70
74
|
query_opts = query_opts_for(query)
|
71
|
-
docs = coll(kind).find(selector, query_opts)
|
72
|
-
docs.map{ |d| unserialize(kind, d) }
|
75
|
+
docs = coll(query.kind).find(selector, query_opts)
|
76
|
+
docs.map{ |d| unserialize(query.kind, d) }
|
77
|
+
rescue EmptyQueryError
|
78
|
+
[]
|
79
|
+
end
|
80
|
+
|
81
|
+
def exec_count(query)
|
82
|
+
query_selector = selector_for(query)
|
83
|
+
query_opts = query_opts_for(query)
|
84
|
+
query_opts.delete(:sort)
|
85
|
+
coll(query.kind).count(query_opts.merge(query: query_selector))
|
86
|
+
rescue EmptyQueryError
|
87
|
+
0
|
73
88
|
end
|
74
89
|
|
75
90
|
def reset!
|
@@ -133,6 +148,7 @@ module Schron
|
|
133
148
|
when '!='
|
134
149
|
selector[mongo_field] = { "$ne" => filter_value }
|
135
150
|
when 'in'
|
151
|
+
raise EmptyQueryError if filter_value.to_a.empty?
|
136
152
|
selector[mongo_field] = { "$in" => filter_value.to_a }
|
137
153
|
when '>'
|
138
154
|
selector[mongo_field] = { "$gt" => filter_value }
|
@@ -16,12 +16,12 @@ module Schron
|
|
16
16
|
@db = db
|
17
17
|
end
|
18
18
|
|
19
|
-
def exec_query(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
def exec_query(query)
|
20
|
+
dataset_for_query(query).all
|
21
|
+
end
|
22
|
+
|
23
|
+
def exec_count(query)
|
24
|
+
dataset_for_query(query).count
|
25
25
|
end
|
26
26
|
|
27
27
|
def multi_get(kind, ids)
|
@@ -94,6 +94,15 @@ module Schron
|
|
94
94
|
hashes.map { |h| unserialize(kind, h) }
|
95
95
|
end
|
96
96
|
|
97
|
+
|
98
|
+
def dataset_for_query(query)
|
99
|
+
dataset = @db[query.kind]
|
100
|
+
dataset = apply_filters(query, dataset)
|
101
|
+
dataset = apply_sorts(query, dataset)
|
102
|
+
dataset = apply_limit_and_offset(query, dataset)
|
103
|
+
dataset
|
104
|
+
end
|
105
|
+
|
97
106
|
def apply_filters(query, data)
|
98
107
|
final = query.filters.reduce(data) do |data, (name, op, value)|
|
99
108
|
case op
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'time'
|
3
3
|
require 'set'
|
4
|
+
require 'bigdecimal'
|
4
5
|
require 'schron/util'
|
5
6
|
module Schron
|
6
7
|
module Datastore
|
@@ -33,7 +34,7 @@ module Schron
|
|
33
34
|
when Array, Set
|
34
35
|
value.map { |v| serialize_value(v) }.to_a
|
35
36
|
when Date, DateTime, Time
|
36
|
-
value.
|
37
|
+
value.to_time.utc
|
37
38
|
when BigDecimal
|
38
39
|
value.to_f
|
39
40
|
else
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Schron
|
2
|
+
class GenericEntity
|
3
|
+
|
4
|
+
attr_reader :attributes
|
5
|
+
|
6
|
+
def initialize(attrs={})
|
7
|
+
@attributes = attrs
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(method, *args)
|
11
|
+
if args.empty? && @attributes.key?(method)
|
12
|
+
@attributes[method]
|
13
|
+
else
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/schron/query.rb
CHANGED
@@ -6,16 +6,23 @@ module Schron
|
|
6
6
|
class Query
|
7
7
|
attr_reader :filters
|
8
8
|
attr_reader :sorts
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :archive
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
@
|
13
|
-
@datastore = datastore
|
11
|
+
def initialize(archive=nil, &block)
|
12
|
+
@archive = archive
|
14
13
|
@filters = []
|
15
14
|
@sorts = []
|
16
15
|
@page = false
|
17
16
|
yield self if block_given?
|
18
17
|
end
|
18
|
+
|
19
|
+
def kind
|
20
|
+
archive.kind
|
21
|
+
end
|
22
|
+
|
23
|
+
def datastore
|
24
|
+
archive.datastore
|
25
|
+
end
|
19
26
|
|
20
27
|
|
21
28
|
##
|
@@ -64,15 +71,21 @@ module Schron
|
|
64
71
|
## Query Terminators
|
65
72
|
|
66
73
|
def all
|
67
|
-
|
74
|
+
raw_results = datastore.exec_query(self)
|
75
|
+
loaded_results = archive.load_all(raw_results)
|
76
|
+
with_pagination(loaded_results)
|
68
77
|
end
|
69
78
|
|
70
79
|
def first
|
71
80
|
limit(1).all.first
|
72
81
|
end
|
73
82
|
|
83
|
+
def count
|
84
|
+
datastore.exec_count(self)
|
85
|
+
end
|
86
|
+
|
74
87
|
def exists?
|
75
|
-
|
88
|
+
count > 0
|
76
89
|
end
|
77
90
|
|
78
91
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
if defined?(RSpec)
|
2
2
|
|
3
3
|
require 'schron/query'
|
4
|
+
require 'schron/generic_archive'
|
4
5
|
shared_examples 'schron datastore' do
|
5
6
|
let(:entity_kind) { :entities }
|
6
7
|
let(:named_kind) { :named }
|
@@ -169,8 +170,10 @@ if defined?(RSpec)
|
|
169
170
|
end
|
170
171
|
|
171
172
|
describe 'exec query' do
|
172
|
-
let(:
|
173
|
-
let(:
|
173
|
+
let(:named_kind_archive) { Schron::GenericArchive.new(ds, kind: named_kind) }
|
174
|
+
let(:query) { Schron::Query.new(named_kind_archive) }
|
175
|
+
let(:entity_kind_archive) { Schron::GenericArchive.new(ds, kind: entity_kind) }
|
176
|
+
let(:no_result_query) { Schron::Query.new(entity_kind_archive) }
|
174
177
|
|
175
178
|
before(:each) do
|
176
179
|
@c = ds.insert(named_kind, name: 'c')
|
@@ -182,140 +185,291 @@ if defined?(RSpec)
|
|
182
185
|
|
183
186
|
describe 'filters' do
|
184
187
|
it 'filters by equality with a hash' do
|
185
|
-
found = query.filter(name: 'b')
|
188
|
+
found = ds.exec_query(query.filter(name: 'b'))
|
186
189
|
expect(found.size).to eq(1)
|
187
190
|
expect(found.first[:id]).to eq(@b[:id])
|
188
191
|
end
|
189
192
|
|
190
193
|
it 'filters by inclusion with a hash' do
|
191
|
-
found = query.filter(name: ['b', 'c'])
|
194
|
+
found = ds.exec_query(query.filter(name: ['b', 'c']))
|
192
195
|
expect(found.size).to eq(2)
|
193
196
|
expect(found.map{ |h| h[:id] }).to include(@b[:id], @c[:id])
|
194
197
|
end
|
195
198
|
|
196
199
|
it 'filters by "=" operator' do
|
197
|
-
found = query.filter(:name, '=', 'b')
|
200
|
+
found = ds.exec_query(query.filter(:name, '=', 'b'))
|
198
201
|
expect(found.size).to eq(1)
|
199
202
|
expect(found.first[:id]).to eq(@b[:id])
|
200
203
|
end
|
201
204
|
|
202
205
|
it 'filters by "in" operator' do
|
203
|
-
found = query.filter(:name, 'in', ['a', 'b'])
|
206
|
+
found = ds.exec_query(query.filter(:name, 'in', ['a', 'b']))
|
204
207
|
expect(found.size).to eq(3)
|
205
208
|
expect(found.map{ |h| h[:id] }).to include(@a1[:id], @a2[:id], @b[:id])
|
206
209
|
end
|
207
210
|
|
208
211
|
it 'filters by ">" operator' do
|
209
|
-
found = query.filter(:name, '>', 'a')
|
212
|
+
found = ds.exec_query(query.filter(:name, '>', 'a'))
|
210
213
|
expect(found.size).to be(2)
|
211
214
|
expect(found.map{ |h| h[:id] }).to include(@b[:id], @c[:id])
|
212
215
|
end
|
213
216
|
|
214
217
|
it 'filters by ">=" operator' do
|
215
|
-
found = query.filter(:name, '>=', 'a')
|
218
|
+
found = ds.exec_query(query.filter(:name, '>=', 'a'))
|
216
219
|
expect(found.size).to be(4)
|
217
220
|
expect(found.map{ |h| h[:id] }).to include(@a1[:id], @a2[:id], @b[:id], @c[:id])
|
218
221
|
end
|
219
222
|
|
220
223
|
it 'filters by "<" operator' do
|
221
|
-
found = query.filter(:name, '<', 'b')
|
224
|
+
found = ds.exec_query(query.filter(:name, '<', 'b'))
|
222
225
|
expect(found.size).to be(2)
|
223
226
|
expect(found.map{ |h| h[:id] }).to include(@a1[:id], @a2[:id])
|
224
227
|
end
|
225
228
|
|
226
229
|
it 'filters by "<=" operator' do
|
227
|
-
found = query.filter(:name, '<=', 'b')
|
230
|
+
found = ds.exec_query(query.filter(:name, '<=', 'b'))
|
228
231
|
expect(found.size).to be(3)
|
229
232
|
expect(found.map{ |h| h[:id] }).to include(@a1[:id], @a2[:id], @b[:id])
|
230
233
|
end
|
231
234
|
|
232
235
|
it 'filters by "!=" operator' do
|
233
|
-
found = query.filter(:name, '!=', 'a')
|
236
|
+
found = ds.exec_query(query.filter(:name, '!=', 'a'))
|
234
237
|
expect(found.size).to eq(3)
|
235
238
|
expect(found.map{ |h| h[:id] }).to include(@c[:id], @b[:id], @nil[:id])
|
236
239
|
end
|
237
240
|
|
238
241
|
it 'returns an empty list if no results match' do
|
239
|
-
expect(query.filter(name: '123')
|
242
|
+
expect(ds.exec_query(query.filter(name: '123'))).to eq([])
|
240
243
|
end
|
241
244
|
|
242
245
|
context 'nil filtering' do
|
243
246
|
it 'filters by = nil' do
|
244
|
-
found = query.filter(name: nil)
|
247
|
+
found = ds.exec_query(query.filter(name: nil))
|
245
248
|
expect(found.size).to eq(1)
|
246
249
|
expect(found.first[:id]).to eq(@nil[:id])
|
247
250
|
end
|
248
251
|
|
249
252
|
it 'filters by != nil' do
|
250
|
-
found = query.filter(:name, '!=', nil)
|
253
|
+
found = ds.exec_query(query.filter(:name, '!=', nil))
|
251
254
|
expect(found.size).to eq(4)
|
252
255
|
expect(found.map{ |h| h[:id] }).to include(@a1[:id], @a2[:id], @b[:id], @c[:id])
|
253
256
|
end
|
254
257
|
|
255
258
|
it 'filters by in with nil' do
|
256
|
-
found = query.filter(:name, 'in', [nil, 'b'])
|
259
|
+
found = ds.exec_query(query.filter(:name, 'in', [nil, 'b']))
|
257
260
|
expect(found.size).to eq(2)
|
258
261
|
expect(found.map{ |h| h[:id] }).to include(@b[:id], @nil[:id])
|
259
262
|
end
|
263
|
+
|
264
|
+
it 'filters by in with an empty list' do
|
265
|
+
found = ds.exec_query(query.filter(:name, 'in', []))
|
266
|
+
expect(found.size).to be(0)
|
267
|
+
end
|
260
268
|
end
|
261
269
|
end
|
262
270
|
|
263
271
|
describe 'limit' do
|
264
272
|
it 'limits the results' do
|
265
|
-
found = query.limit(1)
|
273
|
+
found = ds.exec_query(query.limit(1))
|
266
274
|
expect(found.size).to eq(1)
|
267
275
|
end
|
268
276
|
|
269
277
|
it 'returns an empty list if no results match' do
|
270
278
|
q = no_result_query
|
271
|
-
expect(q.limit(2)
|
279
|
+
expect(ds.exec_query(q.limit(2))).to eq([])
|
272
280
|
end
|
273
281
|
end
|
274
282
|
|
275
283
|
describe 'offset' do
|
276
284
|
it 'offsets the results' do
|
277
285
|
all = 4.times.reduce([]) do |ary, i|
|
278
|
-
ary + query.limit(1).offset(i)
|
286
|
+
ary + ds.exec_query(query.limit(1).offset(i))
|
279
287
|
end
|
280
288
|
all_ids = all.map { |h| h[:id] }
|
281
289
|
expect(all_ids).to include(@a1[:id], @a2[:id], @b[:id], @c[:id])
|
282
290
|
end
|
283
291
|
|
284
292
|
it 'returns an empty list if no results match' do
|
285
|
-
expect(query.offset(10)
|
293
|
+
expect(ds.exec_query(query.offset(10))).to eq([])
|
286
294
|
end
|
287
295
|
end
|
288
296
|
|
289
297
|
describe 'sorts' do
|
290
298
|
it 'sorts in asc direction by default' do
|
291
|
-
found = query.sort(:name)
|
299
|
+
found = ds.exec_query(query.sort(:name))
|
292
300
|
expect(found.map{ |h| h[:name] }).to eq(
|
293
301
|
[nil, 'a', 'a', 'b', 'c']
|
294
302
|
)
|
295
303
|
end
|
296
304
|
|
297
305
|
it 'sorts ascending' do
|
298
|
-
found = query.sort(:name, :asc)
|
306
|
+
found = ds.exec_query(query.sort(:name, :asc))
|
299
307
|
expect(found.map{ |h| h[:name] }).to eq([nil, 'a', 'a', 'b', 'c'])
|
300
308
|
end
|
301
309
|
|
302
310
|
it 'sorts descending' do
|
303
|
-
found = query.sort(:name, :desc)
|
311
|
+
found = ds.exec_query(query.sort(:name, :desc))
|
304
312
|
expect(found.map { |h| h[:name] }).to eq(['c', 'b', 'a', 'a', nil])
|
305
313
|
end
|
306
314
|
|
307
315
|
it 'sorts by multiple fields' do
|
308
|
-
found = query.sort(:name).sort(:id)
|
316
|
+
found = ds.exec_query(query.sort(:name).sort(:id))
|
309
317
|
expected = [@nil[:id]] + [@a1[:id], @a2[:id]].sort + [@b[:id], @c[:id]]
|
310
318
|
expect(found.map { |h| h[:id] }).to eq(expected)
|
311
319
|
end
|
312
320
|
|
313
321
|
it 'returns an empty list if no results match' do
|
314
|
-
expect(no_result_query.sort(:id)
|
322
|
+
expect(ds.exec_query(no_result_query.sort(:id))).to eq([])
|
315
323
|
end
|
316
324
|
end
|
317
325
|
|
318
326
|
end
|
327
|
+
|
328
|
+
describe 'exec count' do
|
329
|
+
let(:named_kind_archive) { Schron::GenericArchive.new(ds, kind: named_kind) }
|
330
|
+
let(:query) { Schron::Query.new(named_kind_archive) }
|
331
|
+
let(:entity_kind_archive) { Schron::GenericArchive.new(ds, kind: entity_kind) }
|
332
|
+
let(:no_result_query) { Schron::Query.new(entity_kind_archive) }
|
333
|
+
|
334
|
+
before(:each) do
|
335
|
+
@c = ds.insert(named_kind, name: 'c')
|
336
|
+
@a1 = ds.insert(named_kind, name: 'a')
|
337
|
+
@b = ds.insert(named_kind, name: 'b')
|
338
|
+
@a2 = ds.insert(named_kind, name: 'a')
|
339
|
+
@nil = ds.insert(named_kind, {name: nil})
|
340
|
+
end
|
341
|
+
|
342
|
+
describe 'filters' do
|
343
|
+
it 'filters by equality with a hash' do
|
344
|
+
found = ds.exec_count(query.filter(name: 'b'))
|
345
|
+
expect(found).to eq(1)
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'filters by inclusion with a hash' do
|
349
|
+
found = ds.exec_count(query.filter(name: ['b', 'c']))
|
350
|
+
expect(found).to eq(2)
|
351
|
+
end
|
352
|
+
|
353
|
+
it 'filters by "=" operator' do
|
354
|
+
found = ds.exec_count(query.filter(:name, '=', 'b'))
|
355
|
+
expect(found).to eq(1)
|
356
|
+
end
|
357
|
+
|
358
|
+
it 'filters by "in" operator' do
|
359
|
+
found = ds.exec_count(query.filter(:name, 'in', ['a', 'b']))
|
360
|
+
expect(found).to eq(3)
|
361
|
+
end
|
362
|
+
|
363
|
+
it 'filters by ">" operator' do
|
364
|
+
found = ds.exec_count(query.filter(:name, '>', 'a'))
|
365
|
+
expect(found).to be(2)
|
366
|
+
end
|
367
|
+
|
368
|
+
it 'filters by ">=" operator' do
|
369
|
+
found = ds.exec_count(query.filter(:name, '>=', 'a'))
|
370
|
+
expect(found).to be(4)
|
371
|
+
end
|
372
|
+
|
373
|
+
it 'filters by "<" operator' do
|
374
|
+
found = ds.exec_count(query.filter(:name, '<', 'b'))
|
375
|
+
expect(found).to be(2)
|
376
|
+
end
|
377
|
+
|
378
|
+
it 'filters by "<=" operator' do
|
379
|
+
found = ds.exec_count(query.filter(:name, '<=', 'b'))
|
380
|
+
expect(found).to be(3)
|
381
|
+
end
|
382
|
+
|
383
|
+
it 'filters by "!=" operator' do
|
384
|
+
found = ds.exec_count(query.filter(:name, '!=', 'a'))
|
385
|
+
expect(found).to eq(3)
|
386
|
+
end
|
387
|
+
|
388
|
+
it 'returns 0 if no results match' do
|
389
|
+
expect(ds.exec_count(query.filter(name: '123'))).to eq(0)
|
390
|
+
end
|
391
|
+
|
392
|
+
context 'nil filtering' do
|
393
|
+
it 'filters by = nil' do
|
394
|
+
found = ds.exec_count(query.filter(name: nil))
|
395
|
+
expect(found).to eq(1)
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'filters by != nil' do
|
399
|
+
found = ds.exec_count(query.filter(:name, '!=', nil))
|
400
|
+
expect(found).to eq(4)
|
401
|
+
end
|
402
|
+
|
403
|
+
it 'filters by in with nil' do
|
404
|
+
found = ds.exec_count(query.filter(:name, 'in', [nil, 'b']))
|
405
|
+
expect(found).to eq(2)
|
406
|
+
end
|
407
|
+
|
408
|
+
it 'filters by in with an empty list' do
|
409
|
+
found = ds.exec_count(query.filter(:name, 'in', []))
|
410
|
+
expect(found).to be(0)
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
describe 'limit' do
|
416
|
+
it 'limits the results' do
|
417
|
+
found = ds.exec_count(query.limit(1))
|
418
|
+
expect(found).to eq(1)
|
419
|
+
end
|
420
|
+
|
421
|
+
it 'returns an empty list if no results match' do
|
422
|
+
q = no_result_query
|
423
|
+
expect(ds.exec_count(q.limit(2))).to eq(0)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
describe 'offset' do
|
428
|
+
it 'offsets the results' do
|
429
|
+
4.times do |i|
|
430
|
+
found = ds.exec_count(query.limit(1).offset(i))
|
431
|
+
expect(found).to eq(1)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'returns an empty list if no results match' do
|
436
|
+
expect(ds.exec_count(query.offset(10))).to eq(0)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
describe 'sorts' do
|
441
|
+
it 'sorts in asc direction by default' do
|
442
|
+
found = ds.exec_count(query.sort(:name))
|
443
|
+
expect(found).to eq(5)
|
444
|
+
end
|
445
|
+
|
446
|
+
it 'sorts ascending' do
|
447
|
+
found = ds.exec_count(query.sort(:name, :asc))
|
448
|
+
expect(found).to eq(5)
|
449
|
+
# expect(found.map{ |h| h[:name] }).to eq([nil, 'a', 'a', 'b', 'c'])
|
450
|
+
end
|
451
|
+
|
452
|
+
it 'sorts descending' do
|
453
|
+
found = ds.exec_count(query.sort(:name, :desc))
|
454
|
+
expect(found).to eq(5)
|
455
|
+
# expect(found.map { |h| h[:name] }).to eq(['c', 'b', 'a', 'a', nil])
|
456
|
+
end
|
457
|
+
|
458
|
+
it 'sorts by multiple fields' do
|
459
|
+
found = ds.exec_count(query.sort(:name).sort(:id))
|
460
|
+
expect(found).to eq(5)
|
461
|
+
# expected = [@nil[:id]] + [@a1[:id], @a2[:id]].sort + [@b[:id], @c[:id]]
|
462
|
+
# expect(found.map { |h| h[:id] }).to eq(expected)
|
463
|
+
end
|
464
|
+
|
465
|
+
it 'returns an empty list if no results match' do
|
466
|
+
# expect(ds.exec_count(no_result_query.sort(:id))).to eq([])
|
467
|
+
expect(ds.exec_count(no_result_query.sort(:id))).to eq(0)
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
end
|
472
|
+
|
319
473
|
end
|
320
474
|
|
321
475
|
describe 'datastore type handling' do
|
data/schron.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "schron"
|
7
|
-
spec.version = "0.0.
|
7
|
+
spec.version = "0.0.3"
|
8
8
|
spec.authors = ["David Faber"]
|
9
9
|
spec.email = ["david@1bios.co"]
|
10
10
|
spec.summary = %q{Repository implementation for entity persistence}
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'schron/query'
|
3
|
+
require 'schron/generic_archive'
|
3
4
|
require 'schron/datastore/memory'
|
4
5
|
|
5
6
|
describe Schron::Query do
|
6
|
-
subject(:query) { described_class.new(
|
7
|
+
subject(:query) { described_class.new(archive) }
|
7
8
|
|
9
|
+
let(:archive) { Schron::GenericArchive.new(ds, kind: kind) }
|
8
10
|
let(:kind) { 'tests' }
|
9
11
|
let(:ds) { Schron::Datastore::Memory.new }
|
10
12
|
|
@@ -43,4 +45,21 @@ describe Schron::Query do
|
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
48
|
+
|
49
|
+
describe 'all' do
|
50
|
+
it 'executes the query and returns all results' do
|
51
|
+
expect(ds).to receive(:exec_query).with(query).and_return('raw results')
|
52
|
+
expect(archive).to receive(:load_all).with('raw results').and_return('loaded results')
|
53
|
+
expect(query.all).to eq('loaded results')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'first' do
|
58
|
+
it 'sets the limit to 1, executes the query, and returns just the first result' do
|
59
|
+
expect(query).to receive(:limit).with(1).and_call_original
|
60
|
+
expect(ds).to receive(:exec_query).with(query).and_return(['raw'])
|
61
|
+
expect(archive).to receive(:load).with('raw').and_return('loaded')
|
62
|
+
expect(query.first).to eq('loaded')
|
63
|
+
end
|
64
|
+
end
|
46
65
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Faber
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -130,6 +130,8 @@ files:
|
|
130
130
|
- lib/schron/datastore/serializer.rb
|
131
131
|
- lib/schron/dsl.rb
|
132
132
|
- lib/schron/error.rb
|
133
|
+
- lib/schron/generic_archive.rb
|
134
|
+
- lib/schron/generic_entity.rb
|
133
135
|
- lib/schron/id.rb
|
134
136
|
- lib/schron/identity_map.rb
|
135
137
|
- lib/schron/paginated_results.rb
|