memstore 1.0.0 → 1.0.1

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.
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.