schron 0.0.2 → 0.0.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/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
|