memstore 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -10,15 +10,21 @@ It’s not in any way supposed to be a “real” database. However, it can repl
10
10
 
11
11
  Add this line to your application's Gemfile:
12
12
 
13
- gem "memstore"
13
+ ```ruby
14
+ gem "memstore"
15
+ ```
14
16
 
15
17
  And then execute:
16
18
 
17
- $ bundle
19
+ ```sh
20
+ $ bundle
21
+ ```
18
22
 
19
23
  Or install it yourself as:
20
24
 
21
- $ gem install memstore
25
+ ```sh
26
+ $ gem install memstore
27
+ ```
22
28
 
23
29
  ## Usage
24
30
 
@@ -40,7 +46,7 @@ Or install it yourself as:
40
46
  Creating a data store is utterly simple:
41
47
 
42
48
  ```ruby
43
- mb = MemStore.new
49
+ store = MemStore.new
44
50
  ```
45
51
 
46
52
  By default, objects are indexed using `Object#hash`.
@@ -48,7 +54,7 @@ By default, objects are indexed using `Object#hash`.
48
54
  If a different property should be used, it can be specified like this:
49
55
 
50
56
  ```ruby
51
- mb = MemStore.new(:id)
57
+ store = MemStore.new(:id)
52
58
  ```
53
59
 
54
60
  The property needs to be truly unique for all objects since it’s used as a hash key internally.
@@ -56,8 +62,8 @@ The property needs to be truly unique for all objects since it’s used as a has
56
62
  An items collection can also be provided on creation:
57
63
 
58
64
  ```ruby
59
- mb = MemStore.new(nil, { ... }) # to use Object.hash as key
60
- mb = MemStore.new(:id, { ... }) # to use custom key
65
+ store = MemStore.new(nil, { ... }) # to use Object.hash as key
66
+ store = MemStore.new(:id, { ... }) # to use custom key
61
67
  ```
62
68
 
63
69
  The collection must be a hash that correctly maps the used key to each item.
@@ -71,15 +77,15 @@ They’re basically the same, but `ObjectStore` accesses items through `item.att
71
77
  `ObjectStore` is the default variant:
72
78
 
73
79
  ```ruby
74
- mb = MemStore.new
80
+ store = MemStore.new
75
81
  # is equal to
76
- mb = MemStore::ObjectStore.new
82
+ store = MemStore::ObjectStore.new
77
83
  ```
78
84
 
79
85
  `HashStore` needs to be created explicitly:
80
86
 
81
87
  ```ruby
82
- mb = MemStore::HashStore.new
88
+ store = MemStore::HashStore.new
83
89
  ```
84
90
 
85
91
  If no key attribute is specified, `HashStore` will also use `Object#hash`.
@@ -89,32 +95,32 @@ If no key attribute is specified, `HashStore` will also use `Object#hash`.
89
95
  `items` provides direct access to the internal items hash.
90
96
 
91
97
  ```ruby
92
- mb.items
98
+ store.items
93
99
  # => {}
94
- mb.items = { 1 => a, 2 => b, 3 => c }
100
+ store.items = { 1 => a, 2 => b, 3 => c }
95
101
  # => { 1 => a, 2 => b, 3 => c }
96
102
  ```
97
103
 
98
104
  `insert` adds one or multiple items and returns the data store itself:
99
105
 
100
106
  ```ruby
101
- mb.insert(a, b, c)
102
- # => mb
107
+ store.insert(a, b, c)
108
+ # => store
103
109
  ```
104
110
 
105
111
  Since it returns the data store, items can be added right after instantiation:
106
112
 
107
113
  ```ruby
108
- mb = MemStore.new.insert(a, b, c)
109
- # => mb
114
+ store = MemStore.new.insert(a, b, c)
115
+ # => store
110
116
  ```
111
117
 
112
118
  MemStore also supports the shovel operator `<<` for adding items.
113
119
  Only one item can be added at a time but it’s chainable:
114
120
 
115
121
  ```ruby
116
- mb << a << b << c
117
- # => mb
122
+ store << a << b << c
123
+ # => store
118
124
  ```
119
125
 
120
126
  ### Retrieving Items
@@ -122,7 +128,7 @@ mb << a << b << c
122
128
  `size` returns the current number of items:
123
129
 
124
130
  ```ruby
125
- mb.size
131
+ store.size
126
132
  # => 3
127
133
  ```
128
134
 
@@ -131,18 +137,18 @@ If a single key is given, a single item will be returned.
131
137
  If multiple keys are given, an array of items will be returned with `nil` when there is no item for a key.
132
138
 
133
139
  ```ruby
134
- mb[1]
140
+ store[1]
135
141
  # => a
136
- mb[1, 2, 3]
142
+ store[1, 2, 3]
137
143
  # => [a, b, c]
138
144
  ```
139
145
 
140
146
  Ranges are also supported and can even be combined with single keys:
141
147
 
142
148
  ```ruby
143
- mb[1..3]
149
+ store[1..3]
144
150
  # => [a, b, c]
145
- mb[1..3, 6]
151
+ store[1..3, 6]
146
152
  # => [a, b, c, f]
147
153
  ```
148
154
 
@@ -155,25 +161,25 @@ If one item is given, it is deleted and returned.
155
161
  If multiple items are given, they are deleted and returned as an array.
156
162
 
157
163
  ```ruby
158
- mb.delete_item(a)
164
+ store.delete_item(a)
159
165
  # => a
160
- mb.delete_items(b, c, d)
166
+ store.delete_items(b, c, d)
161
167
  # => [b, c, d]
162
- mb.delete(e, f, g)
168
+ store.delete(e, f, g)
163
169
  # => [e, f, g]
164
170
  ```
165
171
 
166
172
  This is considered the default use case and therefore also available as `delete`.
167
173
 
168
174
  `delete_keys` (or `delete_key`) deletes items by key and returns them.
169
- Again, one or multiple items can be deleted at a time and even ranges are handled.
175
+ Again, one or multiple items can be deleted at a time and even ranges are accepted.
170
176
 
171
177
  ```ruby
172
- mb.delete_key(1)
178
+ store.delete_key(1)
173
179
  # => a
174
- mb.delete_keys(2, 3, 4)
180
+ store.delete_keys(2, 3, 4)
175
181
  # => [b, c, d]
176
- mb.delete_keys(5..7, 9)
182
+ store.delete_keys(5..7, 9)
177
183
  # => [e, f, g, i]
178
184
  ```
179
185
 
@@ -221,10 +227,10 @@ The hash maps attributes names to conditions that should be tested.
221
227
  Conditions are evaluated using the `===` operator and can be virtually anything:
222
228
 
223
229
  ```ruby
224
- mb.find(name: "Fred", age: 25)
225
- mb.find(name: /red/i, age: 10..30)
226
- mb.find(child: MyClass)
227
- mb.find(child: -> child { child.valid? })
230
+ store.find(name: "Fred", age: 25)
231
+ store.find(name: /red/i, age: 10..30)
232
+ store.find(child: MyClass)
233
+ store.find(child: -> child { child.valid? })
228
234
  ```
229
235
 
230
236
  Additional types can be used in conditions by supporting the `===` operator. For example:
@@ -236,20 +242,20 @@ class Array
236
242
  end
237
243
  end
238
244
 
239
- mb.find age: [23, 25, 27]
245
+ store.find age: [23, 25, 27]
240
246
  ```
241
247
 
242
248
  The block is invoked with every item and can do more complex tests.
243
249
  Its return value is interpreted as a boolean value:
244
250
 
245
251
  ```ruby
246
- mb.find { |item| item.age - item.child.age > 20 }
252
+ store.find { |item| item.age - item.child.age > 20 }
247
253
  ```
248
254
 
249
255
  In addition to the evaluation logic, the arrays returned by all variants of `find` can be merged:
250
256
 
251
257
  ```ruby
252
- mb.find(...) | mb.find(...) | mb.find(...)
258
+ store.find(...) | store.find(...) | store.find(...)
253
259
  ```
254
260
 
255
261
  Note that the pipe operator `|` already eliminates duplicates:
@@ -263,28 +269,43 @@ Note that the pipe operator `|` already eliminates duplicates:
263
269
 
264
270
  ### Serialization
265
271
 
272
+ MemStore support various ways of de-/serializing the data store.
273
+
274
+ - `ObjectStore` supports binary format.
275
+ - `HashStore` supports binary format, hash, [YAML](http://yaml.org/), [JSON](http://www.json.org/) and [MessagePack](http://msgpack.org/).
276
+
277
+ **Important:** When file IO or deserialization fails, all variants of `from_*` return `nil`.
278
+
279
+ The following style ensures that there will be a (correctly configured) data store:
280
+
281
+ ```ruby
282
+ store = MemStore.from_file(file) || MemStore::HashStore(key, items)
283
+ ```
284
+
266
285
  #### Binary
267
286
 
268
- The data store can easily be serialized and restored in binary format:
287
+ Both `ObjectStore` and `HashStore` can easily be serialized to and from binary format:
269
288
 
270
289
  ```ruby
271
- mb.to_file("datastore.bin")
290
+ store.to_binary
291
+ # => binary string
292
+ store.to_file(file)
272
293
  # => number of bytes written
273
- MemStore.from_file("datastore.bin")
274
- # => instance of ObjectStore or HashStore
294
+ MemStore.from_binary(binary)
295
+ # => instance of ObjectStore or HashStore or nil
296
+ MemStore.from_file(file)
297
+ # => instance of ObjectStore or HashStore or nil
275
298
  ```
276
299
 
277
- MemStore will automatically restore the correct class (`ObjectStore`/`HashStore`), key and items.
278
-
279
300
  #### Hash
280
301
 
281
302
  `HashStore` can be converted to and from a hash:
282
303
 
283
304
  ```ruby
284
- h = mb.to_hash
305
+ store.to_hash
285
306
  # => { key: ..., items: { ... } }
286
- MemStore::HashStore.from_hash(h)
287
- # => instance of HashStore
307
+ MemStore::HashStore.from_hash(hash)
308
+ # => instance of HashStore or nil
288
309
  ```
289
310
 
290
311
  #### YAML
@@ -294,14 +315,14 @@ MemStore::HashStore.from_hash(h)
294
315
  ```ruby
295
316
  require "memstore/yaml" # requires "yaml"
296
317
 
297
- mb.to_yaml
318
+ store.to_yaml
298
319
  # => YAML string
299
- mb.to_yaml_file(file)
320
+ store.to_yaml_file(file)
300
321
  # => number of bytes written
301
322
  MemStore::HashStore.from_yaml(yaml)
302
- # => instance of HashStore
323
+ # => instance of HashStore or nil
303
324
  MemStore::HashStore.from_yaml_file(file)
304
- # => instance of HashStore
325
+ # => instance of HashStore or nil
305
326
  ```
306
327
 
307
328
  De/serialization is seamless since YAML can handle symbols and non-string keys (i.e. Psych converts them correctly).
@@ -313,34 +334,34 @@ De/serialization is seamless since YAML can handle symbols and non-string keys (
313
334
  ```ruby
314
335
  require "memstore/json" # requires "json"
315
336
 
316
- mb.to_json
337
+ store.to_json
317
338
  # => JSON string
318
- mb.to_json_file(file)
339
+ store.to_json_file(file)
319
340
  # => number of bytes written
320
341
  MemStore::HashStore.from_json(json)
321
- # => instance of HashStore
342
+ # => instance of HashStore or nil
322
343
  MemStore::HashStore.from_json_file(file)
323
- # => instance of HashStore
344
+ # => instance of HashStore or nil
324
345
  ```
325
346
 
326
347
  **Important:** Symbols will be converted to strings and JSON only allows string keys.
327
348
 
328
349
  ```ruby
329
- mb = MemStore::HashStore.new(:id)
330
- mb << { id: 1 }
331
- mb.to_hash
350
+ store = MemStore::HashStore.new(:id)
351
+ store << { id: 1 }
352
+ store.to_hash
332
353
  # => { :key => :id, :items => { 1 => { :id => 1 } } }
333
- mb = MemStore::HashStore.from_json(mb.to_json)
334
- mb.to_hash
354
+ store = MemStore::HashStore.from_json(store.to_json)
355
+ store.to_hash
335
356
  # => { :key => "id", :items => { "1" => { "id" => 1 } } }
336
357
  ```
337
358
 
338
359
  The following style ensures consistent access before and after serialization:
339
360
 
340
361
  ```ruby
341
- mb = MemStore::HashStore.new("id")
342
- mb << { "id" => "1" }
343
- mb["1"]
362
+ store = MemStore::HashStore.new("id")
363
+ store << { "id" => "1" }
364
+ store["1"]
344
365
  # => { "id" => "1" }
345
366
  ```
346
367
 
@@ -351,41 +372,47 @@ mb["1"]
351
372
  ```ruby
352
373
  require "memstore/msgpack" # requires "msgpack"
353
374
 
354
- mb.to_msgpack
375
+ store.to_msgpack
355
376
  # => MessagePack binary format
356
- mb.to_msgpack_file(file)
377
+ store.to_msgpack_file(file)
357
378
  # => number of bytes written
358
379
  MemStore::HashStore.from_msgpack(msgpack)
359
- # => instance of HashStore
380
+ # => instance of HashStore or nil
360
381
  MemStore::HashStore.from_msgpack_file(file)
361
- # => instance of HashStore
382
+ # => instance of HashStore or nil
362
383
  ```
363
384
 
364
385
  **Important:** Symbols will be converted to strings but non-string keys are allowed.
365
386
 
366
387
  ```ruby
367
- mb = MemStore::HashStore.new(:id)
368
- mb << { id: 1 }
369
- mb.to_hash
388
+ store = MemStore::HashStore.new(:id)
389
+ store << { id: 1 }
390
+ store.to_hash
370
391
  # => { :key => :id, :items => { 1 => { :id => 1 } } }
371
- mb = MemStore::HashStore.from_msgpack(mb.to_msgpack)
372
- mb.to_hash
392
+ store = MemStore::HashStore.from_msgpack(store.to_msgpack)
393
+ store.to_hash
373
394
  # => { :key => "id", :items => { 1 => { "id" => 1 } } }
374
395
  ```
375
396
 
376
397
  The following style ensures consistent access before and after serialization:
377
398
 
378
399
  ```ruby
379
- mb = MemStore::HashStore.new("id")
380
- mb << { "id" => 1 }
381
- mb[1]
400
+ store = MemStore::HashStore.new("id")
401
+ store << { "id" => 1 }
402
+ store[1]
382
403
  # => { "id" => 1 }
383
404
  ```
384
405
 
385
406
  ## Contributing
386
407
 
387
- 1. Fork it
388
- 2. Create your feature branch: `git checkout -b my-new-feature`
389
- 3. Commit your changes: `git commit -am 'Add some feature'`
390
- 4. Push to the branch: `git push origin my-new-feature`
391
- 5. Create new Pull Request
408
+ 1. Fork it on [GitHub](https://github.com/sklppr/memstore).
409
+ 2. Create a feature branch containing your changes:
410
+
411
+ ```sh
412
+ $ git checkout -b feature/my-new-feature
413
+ # code, code, code
414
+ $ git commit -am "Add some feature"
415
+ $ git push origin feature/my-new-feature
416
+ ```
417
+
418
+ 3. Create a Pull Request on [GitHub](https://github.com/sklppr/memstore).
data/lib/memstore.rb CHANGED
@@ -2,12 +2,16 @@ require "memstore/version"
2
2
 
3
3
  module MemStore
4
4
 
5
- def self.new(key=nil)
6
- ObjectStore.new(key)
5
+ def self.new(key=nil, items={})
6
+ ObjectStore.new(key, items)
7
+ end
8
+
9
+ def self.from_binary(binary)
10
+ begin Marshal.load(binary) rescue nil end
7
11
  end
8
12
 
9
13
  def self.from_file(file)
10
- Marshal.load IO.read(file)
14
+ begin self.from_binary(IO.read(file)) rescue nil end
11
15
  end
12
16
 
13
17
  class ObjectStore
@@ -32,7 +36,7 @@ module MemStore
32
36
  def [](*keys)
33
37
  return @items[keys.first] if keys.length == 1 && !keys.first.is_a?(Range)
34
38
  keys.inject [] do |items, key|
35
- if key.is_a? Range then key.inject(items) { |i, k| i << @items[k] }
39
+ if key.is_a?(Range) then key.inject(items) { |i, k| i << @items[k] }
36
40
  else items << @items[key] end
37
41
  end
38
42
  end
@@ -51,7 +55,7 @@ module MemStore
51
55
  def delete_keys(*keys)
52
56
  return @items.delete(keys.first) if keys.length == 1 && !keys.first.is_a?(Range)
53
57
  keys.inject [] do |items, key|
54
- if key.is_a? Range then key.inject(items) { |i, k| i << @items.delete(k) }
58
+ if key.is_a?(Range) then key.inject(items) { |i, k| i << @items.delete(k) }
55
59
  else items << @items.delete(key) end
56
60
  end
57
61
  end
@@ -99,8 +103,12 @@ module MemStore
99
103
  all.detect { |item| instance_exec(item, conditions, block, &FIND_NONE) }
100
104
  end
101
105
 
106
+ def to_binary
107
+ Marshal.dump(self)
108
+ end
109
+
102
110
  def to_file(file)
103
- IO.write file, Marshal.dump(self)
111
+ IO.write(file, self.to_binary)
104
112
  end
105
113
 
106
114
  private
@@ -138,7 +146,14 @@ module MemStore
138
146
  class HashStore < ObjectStore
139
147
 
140
148
  def self.from_hash(hash)
141
- self.new(hash[:key] || hash["key"], hash[:items] || hash["items"])
149
+ begin
150
+ key = hash[:key] || hash["key"]
151
+ items = hash[:items] || hash["items"]
152
+ return nil if key.nil? || items.nil?
153
+ self.new(key, items)
154
+ rescue
155
+ nil
156
+ end
142
157
  end
143
158
 
144
159
  def initialize(key=nil, items={})
data/lib/memstore/json.rb CHANGED
@@ -9,15 +9,15 @@ module MemStore
9
9
  end
10
10
 
11
11
  def to_json_file(file)
12
- IO.write file, self.to_json
12
+ IO.write(file, self.to_json)
13
13
  end
14
14
 
15
15
  def self.from_json(json)
16
- self.from_hash JSON.parse(json)
16
+ begin self.from_hash(JSON.parse(json)) rescue nil end
17
17
  end
18
18
 
19
19
  def self.from_json_file(file)
20
- self.from_json IO.read(file)
20
+ begin self.from_json(IO.read(file)) rescue nil end
21
21
  end
22
22
 
23
23
  end
@@ -9,15 +9,15 @@ module MemStore
9
9
  end
10
10
 
11
11
  def to_msgpack_file(file)
12
- IO.write file, self.to_msgpack
12
+ IO.write(file, self.to_msgpack)
13
13
  end
14
14
 
15
15
  def self.from_msgpack(msgpack)
16
- self.from_hash MessagePack.unpack(msgpack)
16
+ begin self.from_hash(MessagePack.unpack(msgpack)) rescue nil end
17
17
  end
18
18
 
19
19
  def self.from_msgpack_file(file)
20
- self.from_msgpack IO.read(file)
20
+ begin self.from_msgpack(IO.read(file)) rescue nil end
21
21
  end
22
22
 
23
23
  end
@@ -1,3 +1,3 @@
1
1
  module MemStore
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
data/lib/memstore/yaml.rb CHANGED
@@ -9,15 +9,15 @@ module MemStore
9
9
  end
10
10
 
11
11
  def to_yaml_file(file)
12
- IO.write file, self.to_yaml
12
+ IO.write(file, self.to_yaml)
13
13
  end
14
14
 
15
15
  def self.from_yaml(yaml)
16
- self.from_hash YAML.load(yaml)
16
+ begin self.from_hash(YAML.load(yaml)) rescue nil end
17
17
  end
18
18
 
19
19
  def self.from_yaml_file(file)
20
- self.from_yaml IO.read(file)
20
+ begin self.from_yaml(IO.read(file)) rescue nil end
21
21
  end
22
22
 
23
23
  end
@@ -6,26 +6,26 @@ require "memstore"
6
6
  require "memstore/json"
7
7
 
8
8
  describe MemStore::HashStore do
9
-
10
- before do
11
- @key = "id"
12
- @mb = MemStore::HashStore.new(@key)
13
- 10.times { |i| @mb << { "id" => i.to_s } }
14
- end
9
+
10
+ before do
11
+ @key = "id"
12
+ @store = MemStore::HashStore.new(@key)
13
+ 10.times { |i| @store << { "id" => i.to_s } }
14
+ end
15
15
 
16
- it "can be converted to and from JSON" do
17
- restored = MemStore::HashStore.from_json(@mb.to_json)
18
- restored.items.must_equal @mb.items
19
- restored.instance_variable_get(:@key).must_equal @key
20
- end
16
+ it "can be converted to and from JSON" do
17
+ restored = MemStore::HashStore.from_json(@store.to_json)
18
+ restored.items.must_equal @store.items
19
+ restored.instance_variable_get(:@key).must_equal @key
20
+ end
21
21
 
22
- it "can be serialized to and deserialized from a JSON file" do
23
- tmp = Tempfile.new("memstore_json")
24
- @mb.to_json_file(tmp)
25
- restored = MemStore::HashStore.from_json_file(tmp)
26
- restored.items.must_equal @mb.items
27
- restored.instance_variable_get(:@key).must_equal @key
28
- tmp.unlink
29
- end
22
+ it "can be serialized to and deserialized from a JSON file" do
23
+ tmp = Tempfile.new("memstore")
24
+ @store.to_json_file(tmp)
25
+ restored = MemStore::HashStore.from_json_file(tmp)
26
+ restored.items.must_equal @store.items
27
+ restored.instance_variable_get(:@key).must_equal @key
28
+ tmp.unlink
29
+ end
30
30
 
31
31
  end
@@ -6,26 +6,26 @@ require "memstore"
6
6
  require "memstore/msgpack"
7
7
 
8
8
  describe MemStore::HashStore do
9
-
10
- before do
11
- @key = "id"
12
- @mb = MemStore::HashStore.new(@key)
13
- 10.times { |i| @mb << { "id" => i } }
14
- end
9
+
10
+ before do
11
+ @key = "id"
12
+ @store = MemStore::HashStore.new(@key)
13
+ 10.times { |i| @store << { "id" => i } }
14
+ end
15
15
 
16
- it "can be converted to and from MessagePack" do
17
- restored = MemStore::HashStore.from_msgpack(@mb.to_msgpack)
18
- restored.items.must_equal @mb.items
19
- restored.instance_variable_get(:@key).must_equal @key
20
- end
16
+ it "can be converted to and from MessagePack" do
17
+ restored = MemStore::HashStore.from_msgpack(@store.to_msgpack)
18
+ restored.items.must_equal @store.items
19
+ restored.instance_variable_get(:@key).must_equal @key
20
+ end
21
21
 
22
- it "can be serialized to and deserialized from a MessagePack file" do
23
- tmp = Tempfile.new("memstore_json")
24
- @mb.to_msgpack_file(tmp)
25
- restored = MemStore::HashStore.from_msgpack_file(tmp)
26
- restored.items.must_equal @mb.items
27
- restored.instance_variable_get(:@key).must_equal @key
28
- tmp.unlink
29
- end
22
+ it "can be serialized to and deserialized from a MessagePack file" do
23
+ tmp = Tempfile.new("memstore")
24
+ @store.to_msgpack_file(tmp)
25
+ restored = MemStore::HashStore.from_msgpack_file(tmp)
26
+ restored.items.must_equal @store.items
27
+ restored.instance_variable_get(:@key).must_equal @key
28
+ tmp.unlink
29
+ end
30
30
 
31
31
  end
@@ -4,189 +4,235 @@ require "minitest/autorun"
4
4
  require "tempfile"
5
5
  require "memstore"
6
6
 
7
+ class Dummy
8
+
9
+ attr_accessor :id, :name, :child
10
+
11
+ def initialize(id, name=nil, child=nil)
12
+ @id, @name, @child = id, name, child
13
+ end
14
+
15
+ def ==(obj)
16
+ obj.is_a?(Dummy) &&
17
+ obj.id == @id &&
18
+ obj.name == @name &&
19
+ obj.child == @child
20
+ end
21
+
22
+ end
23
+
7
24
  describe MemStore::ObjectStore do
8
-
9
- it "can be instantiated with items" do
10
- h = { a: 1, b: 2, c: 3 }
11
- mb = MemStore::ObjectStore.new(nil, h)
12
- mb.items.must_equal h
13
- end
14
-
15
- it "is the default when instantiating MemStore" do
16
- MemStore.new.must_be_instance_of MemStore::ObjectStore
17
- end
18
-
19
- it "indexes items by Object#hash by default" do
20
- o = Object.new
21
- mb = MemStore::ObjectStore.new.insert(o)
22
- mb.items[o.hash].must_equal o
23
- end
24
-
25
- it "indexes items using a custom key" do
26
- o = Struct.new(:id).new(id: "custom key")
27
- mb = MemStore::ObjectStore.new(:id).insert(o)
28
- mb.items[o.id].must_equal o
29
- end
30
-
31
- it "can be serialized and deserialized" do
32
- tmp = Tempfile.new("memstore")
33
- MemStore::ObjectStore.new.to_file tmp
34
- MemStore.from_file(tmp).must_be_instance_of MemStore::ObjectStore
35
- tmp.unlink
36
- end
25
+
26
+ it "can be instantiated with items" do
27
+ h = { a: 1, b: 2, c: 3 }
28
+ store = MemStore::ObjectStore.new(nil, h)
29
+ store.items.must_equal h
30
+ end
31
+
32
+ it "is the default when instantiating MemStore" do
33
+ MemStore.new.must_be_instance_of MemStore::ObjectStore
34
+ end
35
+
36
+ it "indexes items by Object#hash by default" do
37
+ o = Object.new
38
+ store = MemStore::ObjectStore.new.insert(o)
39
+ store.items[o.hash].must_equal o
40
+ end
41
+
42
+ it "indexes items using a custom key" do
43
+ o = Dummy.new("custom key")
44
+ store = MemStore::ObjectStore.new(:id).insert(o)
45
+ store.items[o.id].must_equal o
46
+ end
47
+
48
+ it "can be converted to and from binary" do
49
+ o = Dummy.new("custom key")
50
+ store = MemStore::ObjectStore.new(:id).insert(o)
51
+ restored = MemStore.from_binary(store.to_binary)
52
+ restored.must_be_instance_of MemStore::ObjectStore
53
+ restored.items.must_equal store.items
54
+ restored.instance_variable_get(:@key).must_equal :id
55
+ end
56
+
57
+ it "can be serialized to and deserialized from a binary file" do
58
+ tmp = Tempfile.new("memstore")
59
+ MemStore::ObjectStore.new.to_file tmp
60
+ MemStore.from_file(tmp).must_be_instance_of MemStore::ObjectStore
61
+ tmp.unlink
62
+ end
37
63
 
38
64
  end
39
65
 
40
66
  describe MemStore::HashStore do
41
67
 
42
- it "can be instantiated with items" do
43
- h = { a: 1, b: 2, c: 3 }
44
- mb = MemStore::HashStore.new(nil, h)
45
- mb.items.must_equal h
46
- end
47
-
48
- it "indexes items by Object#hash by default" do
49
- h = {}
50
- mb = MemStore::HashStore.new.insert(h)
51
- mb.items[h.hash].must_equal h
52
- end
53
-
54
- it "indexes items using a custom key" do
55
- h = { id: "custom key" }
56
- mb = MemStore::HashStore.new(:id).insert(h)
57
- mb.items[h[:id]].must_equal h
58
- end
59
-
60
- it "can be serialized and deserialized" do
61
- tmp = Tempfile.new("memstore")
62
- MemStore::HashStore.new.to_file tmp
63
- MemStore.from_file(tmp).must_be_instance_of MemStore::HashStore
64
- tmp.unlink
65
- end
66
-
67
- it "can be converted to and from a hash" do
68
- mb = MemStore::HashStore.new(:id)
69
- 10.times { |i| mb << { id: i } }
70
- restored = MemStore::HashStore.from_hash(mb.to_hash)
71
- restored.items.must_equal mb.items
72
- restored.instance_variable_get(:@key).must_equal :id
73
- end
68
+ it "can be instantiated with items" do
69
+ h = { a: 1, b: 2, c: 3 }
70
+ store = MemStore::HashStore.new(nil, h)
71
+ store.items.must_equal h
72
+ end
73
+
74
+ it "indexes items by Object#hash by default" do
75
+ h = {}
76
+ store = MemStore::HashStore.new.insert(h)
77
+ store.items[h.hash].must_equal h
78
+ end
79
+
80
+ it "indexes items using a custom key" do
81
+ h = { id: "custom key" }
82
+ store = MemStore::HashStore.new(:id).insert(h)
83
+ store.items[h[:id]].must_equal h
84
+ end
85
+
86
+ it "can be converted to and from binary" do
87
+ store = MemStore::HashStore.new(:id)
88
+ 10.times { |i| store << { id: i } }
89
+ restored = MemStore.from_binary(store.to_binary)
90
+ restored.must_be_instance_of MemStore::HashStore
91
+ restored.items.must_equal store.items
92
+ restored.instance_variable_get(:@key).must_equal :id
93
+ end
94
+
95
+ it "can be serialized to and deserialized from a binary file" do
96
+ tmp = Tempfile.new("memstore")
97
+ MemStore::HashStore.new.to_file tmp
98
+ MemStore.from_file(tmp).must_be_instance_of MemStore::HashStore
99
+ tmp.unlink
100
+ end
101
+
102
+ it "can be converted to and from a hash" do
103
+ store = MemStore::HashStore.new(:id)
104
+ 10.times { |i| store << { id: i } }
105
+ restored = MemStore::HashStore.from_hash(store.to_hash)
106
+ restored.items.must_equal store.items
107
+ restored.instance_variable_get(:@key).must_equal :id
108
+ end
109
+
110
+ it "returns nil when conversion from hash fails" do
111
+ MemStore::HashStore.from_hash(nil).must_equal nil
112
+ MemStore::HashStore.from_hash({}).must_equal nil
113
+ end
74
114
 
75
115
  end
76
116
 
77
117
  describe MemStore do
78
118
 
79
- before do
80
- @mb = MemStore.new(:to_i)
81
- # Use float as objects and integer as key
82
- 10.times { |i| @mb << i.to_f }
83
- end
84
-
85
- it "returns a single item by itself" do
86
- @mb[3].must_equal 3.0
87
- end
88
-
89
- it "returns multiple items as an array" do
90
- @mb[3, 4, 5, 6].must_equal [3.0, 4.0, 5.0, 6.0]
91
- end
92
-
93
- it "returns multiple items using a Range as an array" do
94
- @mb[0..9].must_equal @mb.all
95
- end
96
-
97
- it "deletes a single item by reference and returns it by itself" do
98
- @mb.delete_item(3.0).must_equal 3.0
99
- end
100
-
101
- it "deletes multiple items by reference and returns them" do
102
- @mb.delete_items(3.0, 4.0, 5.0, 6.0).must_equal [3.0, 4.0, 5.0, 6.0]
103
- @mb.all.must_equal [0.0, 1.0, 2.0, 7.0, 8.0, 9.0]
104
- end
105
-
106
- it "deletes a single item by key and returns it by itself" do
107
- @mb.delete_key(3).must_equal 3.0
108
- end
109
-
110
- it "deletes multiple items by key and returns them as an array" do
111
- @mb.delete_keys(3, 4, 5, 6).must_equal [3.0, 4.0, 5.0, 6.0]
112
- @mb.all.must_equal [0.0, 1.0, 2.0, 7.0, 8.0, 9.0]
113
- end
114
-
115
- it "deletes multiple items by key using a Range and returns them as an array" do
116
- @mb.delete_keys(3..6).must_equal [3.0, 4.0, 5.0, 6.0]
117
- @mb.all.must_equal [0.0, 1.0, 2.0, 7.0, 8.0, 9.0]
118
- end
119
-
120
- it "can be serialized and deserialized" do
121
- tmp = Tempfile.new("memstore")
122
- @mb.to_file tmp
123
- MemStore.from_file(tmp).items.must_equal @mb.items
124
- tmp.unlink
125
- end
119
+ before do
120
+ @store = MemStore.new(:to_i)
121
+ # Use float as objects and integer as key
122
+ 10.times { |i| @store << i.to_f }
123
+ end
124
+
125
+ it "returns a single item by itself" do
126
+ @store[3].must_equal 3.0
127
+ end
128
+
129
+ it "returns multiple items as an array" do
130
+ @store[3, 4, 5, 6].must_equal [3.0, 4.0, 5.0, 6.0]
131
+ end
132
+
133
+ it "returns multiple items using a Range as an array" do
134
+ @store[0..9].must_equal @store.all
135
+ end
136
+
137
+ it "deletes a single item by reference and returns it by itself" do
138
+ @store.delete_item(3.0).must_equal 3.0
139
+ end
140
+
141
+ it "deletes multiple items by reference and returns them" do
142
+ @store.delete_items(3.0, 4.0, 5.0, 6.0).must_equal [3.0, 4.0, 5.0, 6.0]
143
+ @store.all.must_equal [0.0, 1.0, 2.0, 7.0, 8.0, 9.0]
144
+ end
145
+
146
+ it "deletes a single item by key and returns it by itself" do
147
+ @store.delete_key(3).must_equal 3.0
148
+ end
149
+
150
+ it "deletes multiple items by key and returns them as an array" do
151
+ @store.delete_keys(3, 4, 5, 6).must_equal [3.0, 4.0, 5.0, 6.0]
152
+ @store.all.must_equal [0.0, 1.0, 2.0, 7.0, 8.0, 9.0]
153
+ end
154
+
155
+ it "deletes multiple items by key using a Range and returns them as an array" do
156
+ @store.delete_keys(3..6).must_equal [3.0, 4.0, 5.0, 6.0]
157
+ @store.all.must_equal [0.0, 1.0, 2.0, 7.0, 8.0, 9.0]
158
+ end
159
+
160
+ it "can be serialized to and deserialized from a binary file" do
161
+ tmp = Tempfile.new("memstore")
162
+ @store.to_file tmp
163
+ MemStore.from_file(tmp).items.must_equal @store.items
164
+ tmp.unlink
165
+ end
166
+
167
+ it "returns nil when conversion from binary fails" do
168
+ MemStore.from_binary(nil).must_equal nil
169
+ end
170
+
171
+ it "returns nil when deserialization from binary file fails" do
172
+ MemStore.from_file("does_not_exist").must_equal nil
173
+ end
126
174
 
127
175
  end
128
176
 
129
- Dummy = Struct.new(:id, :name, :child)
130
-
131
177
  describe MemStore do
132
178
 
133
- before do
134
- @mb = MemStore.new
135
- strings = %w(foo moo boo faa maa baa foa moa boa lao)
136
- classes = [String, Array]
137
- 10.times do |i|
138
- @mb << Dummy.new(i, strings[i], classes[i%2].new)
139
- end
140
- end
141
-
142
- it "finds all items fulfilling all conditions" do
143
- matches = @mb.find_all(id: 3..7, child: String)
144
- matches.collect{ |m| m.id }.must_equal [4, 6]
145
- end
146
-
147
- it "finds all items fulfilling at least one condition" do
148
- matches = @mb.find_any(id: 3..7, child: String)
149
- matches.collect{ |m| m.id }.must_equal [0, 2, 3, 4, 5, 6, 7, 8]
150
- end
151
-
152
- it "finds all items fulfilling exactly one condition" do
153
- matches = @mb.find_one(name: /o/, child: String)
154
- matches.collect{ |m| m.id }.must_equal [1, 4, 7, 9]
155
- end
156
-
157
- it "finds all items violating at least one condition" do
158
- matches = @mb.find_not_all(name: /o/, child: String)
159
- matches.collect{ |m| m.id }.must_equal [1, 3, 4, 5, 7, 9]
160
- end
161
-
162
- it "finds all items violating all conditions" do
163
- matches = @mb.find_none(name: /o/, child: String)
164
- matches.collect{ |m| m.id }.must_equal [3, 5]
165
- end
166
-
167
- it "finds the first item fulfilling all conditions" do
168
- match = @mb.first_all(id: 3..7, child: String)
169
- match.id.must_equal 4
170
- end
171
-
172
- it "finds the first item fulfilling at least one condition" do
173
- match = @mb.first_any(id: 3..7, child: String)
174
- match.id.must_equal 0
175
- end
176
-
177
- it "finds the first item fulfilling exactly one condition" do
178
- match = @mb.first_one(name: /o/, child: String)
179
- match.id.must_equal 1
180
- end
181
-
182
- it "finds the first item violating at least one condition" do
183
- match = @mb.first_not_all(name: /o/, child: String)
184
- match.id.must_equal 1
185
- end
186
-
187
- it "finds the first item violating all conditions" do
188
- match = @mb.first_none(name: /o/, child: String)
189
- match.id.must_equal 3
190
- end
179
+ before do
180
+ @store = MemStore.new
181
+ strings = %w(foo moo boo faa maa baa foa moa boa lao)
182
+ classes = [String, Array]
183
+ 10.times do |i|
184
+ @store << Dummy.new(i, strings[i], classes[i%2].new)
185
+ end
186
+ end
187
+
188
+ it "finds all items fulfilling all conditions" do
189
+ matches = @store.find_all(id: 3..7, child: String)
190
+ matches.collect{ |m| m.id }.must_equal [4, 6]
191
+ end
192
+
193
+ it "finds all items fulfilling at least one condition" do
194
+ matches = @store.find_any(id: 3..7, child: String)
195
+ matches.collect{ |m| m.id }.must_equal [0, 2, 3, 4, 5, 6, 7, 8]
196
+ end
197
+
198
+ it "finds all items fulfilling exactly one condition" do
199
+ matches = @store.find_one(name: /o/, child: String)
200
+ matches.collect{ |m| m.id }.must_equal [1, 4, 7, 9]
201
+ end
202
+
203
+ it "finds all items violating at least one condition" do
204
+ matches = @store.find_not_all(name: /o/, child: String)
205
+ matches.collect{ |m| m.id }.must_equal [1, 3, 4, 5, 7, 9]
206
+ end
207
+
208
+ it "finds all items violating all conditions" do
209
+ matches = @store.find_none(name: /o/, child: String)
210
+ matches.collect{ |m| m.id }.must_equal [3, 5]
211
+ end
212
+
213
+ it "finds the first item fulfilling all conditions" do
214
+ match = @store.first_all(id: 3..7, child: String)
215
+ match.id.must_equal 4
216
+ end
217
+
218
+ it "finds the first item fulfilling at least one condition" do
219
+ match = @store.first_any(id: 3..7, child: String)
220
+ match.id.must_equal 0
221
+ end
222
+
223
+ it "finds the first item fulfilling exactly one condition" do
224
+ match = @store.first_one(name: /o/, child: String)
225
+ match.id.must_equal 1
226
+ end
227
+
228
+ it "finds the first item violating at least one condition" do
229
+ match = @store.first_not_all(name: /o/, child: String)
230
+ match.id.must_equal 1
231
+ end
232
+
233
+ it "finds the first item violating all conditions" do
234
+ match = @store.first_none(name: /o/, child: String)
235
+ match.id.must_equal 3
236
+ end
191
237
 
192
238
  end
@@ -6,26 +6,26 @@ require "memstore"
6
6
  require "memstore/yaml"
7
7
 
8
8
  describe MemStore::HashStore do
9
-
10
- before do
11
- @key = :id
12
- @mb = MemStore::HashStore.new(@key)
13
- 10.times { |i| @mb << { id: i } }
14
- end
9
+
10
+ before do
11
+ @key = :id
12
+ @store = MemStore::HashStore.new(@key)
13
+ 10.times { |i| @store << { id: i } }
14
+ end
15
15
 
16
- it "can be converted to and from YAML" do
17
- restored = MemStore::HashStore.from_yaml(@mb.to_yaml)
18
- restored.items.must_equal @mb.items
19
- restored.instance_variable_get(:@key).must_equal @key
20
- end
16
+ it "can be converted to and from YAML" do
17
+ restored = MemStore::HashStore.from_yaml(@store.to_yaml)
18
+ restored.items.must_equal @store.items
19
+ restored.instance_variable_get(:@key).must_equal @key
20
+ end
21
21
 
22
- it "can be serialized to and deserialized from a YAML file" do
23
- tmp = Tempfile.new("memstore_yaml")
24
- @mb.to_yaml_file(tmp)
25
- restored = MemStore::HashStore.from_yaml_file(tmp)
26
- restored.items.must_equal @mb.items
27
- restored.instance_variable_get(:@key).must_equal @key
28
- tmp.unlink
29
- end
22
+ it "can be serialized to and deserialized from a YAML file" do
23
+ tmp = Tempfile.new("memstore")
24
+ @store.to_yaml_file(tmp)
25
+ restored = MemStore::HashStore.from_yaml_file(tmp)
26
+ restored.items.must_equal @store.items
27
+ restored.instance_variable_get(:@key).must_equal @key
28
+ tmp.unlink
29
+ end
30
30
 
31
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memstore
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-19 00:00:00.000000000 Z
12
+ date: 2013-02-20 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: MemStore is a simple in-memory data store that supports adding, retrieving
15
15
  and deleting items as well as complex search queries and easy serialization.