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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a8e1d0962975ce0ce8d619f4e757b60cdf631e82
4
- data.tar.gz: 36477336e2e1a6c356cd4ba95430eb61e3d91947
3
+ metadata.gz: 7769c035395e049f20cbede7cda51f0b39c8ed28
4
+ data.tar.gz: 6eacb27127b5d4770d36dd17692697b1bd39d93e
5
5
  SHA512:
6
- metadata.gz: f691c4bf156243994fa5ca0d0e3532b88f9dfc26442a51e56036d0cec8bd11558a1789bc00a573d0f5e2c93030505da18784c82663d4f7b0c7fdd6bb04abf294
7
- data.tar.gz: 33fca3e587a68959a994bd584883426c5169340c2054b325b5a610f307408e6378c3601d8b659aa5f483b1b03e61e3fbd9ec31c05b28b19e2f7c189ab6771e48
6
+ metadata.gz: e2f2c532a880389220906e087c45772d8430159ff4b102c33aa770793ba1c0e52e7db0714cfb6e3833c3a463e9aa3b273950d362d1e490b58d5600565280fe62
7
+ data.tar.gz: a3becfbd86f34a23e6a5d3038f35df103ce72cadb31753fbacae795574644987488a9fd8c83693a92fc458f2bc04a78dfc344e116a857ceeee283408b40babca
@@ -25,14 +25,15 @@ module Schron
25
25
  end
26
26
 
27
27
  def query(&block)
28
- load_all(Query.new(@kind, @datastore, &block).all)
28
+ Query.new(self, &block)
29
29
  end
30
30
 
31
- def first(&block)
32
- query do |q|
33
- yield q if block_given?
34
- q.limit(1)
35
- end.first
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 with setting ENV['SCHRON_RESET'] to 1"
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(kind, 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).find(id_selector(id)).first
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(kind, 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(kind, query)
20
- dataset = @db[kind]
21
- dataset = apply_filters(query, dataset)
22
- dataset = apply_sorts(query, dataset)
23
- dataset = apply_limit_and_offset(query, dataset)
24
- dataset.all
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.to_datetime.iso8601(9)
37
+ value.to_time.utc
37
38
  when BigDecimal
38
39
  value.to_f
39
40
  else
@@ -0,0 +1,10 @@
1
+ require 'schron/archive'
2
+ require 'schron/generic_entity'
3
+
4
+ module Schron
5
+ class GenericArchive
6
+ include Schron::Archive
7
+
8
+ entity_class GenericEntity
9
+ end
10
+ end
@@ -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
@@ -6,16 +6,23 @@ module Schron
6
6
  class Query
7
7
  attr_reader :filters
8
8
  attr_reader :sorts
9
- attr_reader :kind
9
+ attr_reader :archive
10
10
 
11
- def initialize(kind=nil, datastore=nil &block)
12
- @kind = kind
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
- with_pagination(@datastore.exec_query(@kind, self))
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
- !all.empty?
88
+ count > 0
76
89
  end
77
90
 
78
91
 
@@ -19,7 +19,7 @@ if defined?(RSpec)
19
19
  expect(archive.datastore).to receive(:exec_query).and_call_original
20
20
  results = archive.query do |q|
21
21
  expect(q.kind).to eq(archive.kind)
22
- end
22
+ end.all
23
23
  expect_same_entity results.first, entity
24
24
  end
25
25
  end
@@ -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(:query) { Schron::Query.new(named_kind, ds) }
173
- let(:no_result_query) { Schron::Query.new(entity_kind, ds) }
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').all
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']).all
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').all
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']).all
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').all
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').all
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').all
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').all
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').all
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').all).to eq([])
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).all
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).all
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']).all
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).all
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).all).to eq([])
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).all
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).all).to eq([])
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).all
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).all
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).all
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).all
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).all).to eq([])
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
@@ -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.2"
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(kind, ds) }
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.2
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-08 00:00:00.000000000 Z
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