memstore 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +20 -18
- data/lib/memstore.rb +34 -3
- data/lib/memstore/version.rb +1 -1
- data/spec/memstore_spec.rb +53 -23
- metadata +1 -1
data/README.md
CHANGED
@@ -125,10 +125,10 @@ store << a << b << c
|
|
125
125
|
|
126
126
|
### Retrieving Items
|
127
127
|
|
128
|
-
`size` returns the current number of items:
|
128
|
+
`length` (or `size`) returns the current number of items:
|
129
129
|
|
130
130
|
```ruby
|
131
|
-
store.
|
131
|
+
store.length
|
132
132
|
# => 3
|
133
133
|
```
|
134
134
|
|
@@ -187,21 +187,27 @@ store.delete_keys(5..7, 9)
|
|
187
187
|
|
188
188
|
The following methods are available to query the data store:
|
189
189
|
|
190
|
-
- `find_all` (`find`)
|
190
|
+
- `find_all` (also available as `find`)
|
191
191
|
- `find_any`
|
192
192
|
- `find_one`
|
193
193
|
- `find_not_all`
|
194
194
|
- `find_none`
|
195
|
-
- `first_all` (`first`)
|
195
|
+
- `first_all` (also available as `first`)
|
196
196
|
- `first_any`
|
197
197
|
- `first_one`
|
198
198
|
- `first_not_all`
|
199
199
|
- `first_none`
|
200
|
+
- `count_all` (also available as `count`)
|
201
|
+
- `count_any`
|
202
|
+
- `count_one`
|
203
|
+
- `count_not_all`
|
204
|
+
- `count_none`
|
200
205
|
|
201
206
|
The first part indicates what is returned:
|
202
207
|
|
203
208
|
- `find_*` returns all matches.
|
204
209
|
- `first_*` returns the first match.
|
210
|
+
- `count_*` returns the number of matches.
|
205
211
|
|
206
212
|
The second part indicates how conditions are evaluated:
|
207
213
|
|
@@ -213,13 +219,11 @@ The second part indicates how conditions are evaluated:
|
|
213
219
|
|
214
220
|
In other words:
|
215
221
|
|
216
|
-
- `all` means `condition && condition &&
|
217
|
-
- `any` means `condition || condition ||
|
218
|
-
- `one` means `condition ^ condition ^ ...` (XOR)
|
219
|
-
- `not all` means `!(condition && condition && ...)` or `!condition || !condition ||
|
220
|
-
- `none` means `!(condition || condition || ...)` or `!condition && !condition &&
|
221
|
-
|
222
|
-
For convenience, `find` is aliased to `find_all` and `first` to `first_all`.
|
222
|
+
- `all` means `condition && condition && ...`.
|
223
|
+
- `any` means `condition || condition || ...`.
|
224
|
+
- `one` means `condition ^ condition ^ ...` (XOR).
|
225
|
+
- `not all` means `!(condition && condition && ...)` or `!condition || !condition || ...`.
|
226
|
+
- `none` means `!(condition || condition || ...)` or `!condition && !condition && ...`.
|
223
227
|
|
224
228
|
All variants take a `conditions` hash and an optional block.
|
225
229
|
|
@@ -242,17 +246,17 @@ class Array
|
|
242
246
|
end
|
243
247
|
end
|
244
248
|
|
245
|
-
store.find
|
249
|
+
store.find(age: [23, 25, 27])
|
246
250
|
```
|
247
251
|
|
248
|
-
The block is invoked with
|
249
|
-
Its return value is interpreted as a boolean value:
|
252
|
+
The block is invoked with the item *after* the conditions are evaluated. It should return a boolean value:
|
250
253
|
|
251
254
|
```ruby
|
252
|
-
store.find { |item| item.age - item.child.age > 20 }
|
255
|
+
store.find(age: 25) { |item| item.age - item.child.age > 20 }
|
256
|
+
# is evaluated as (item.age == 25) && (item.age - item.child.age > 20)
|
253
257
|
```
|
254
258
|
|
255
|
-
In addition to the evaluation logic, the arrays returned by all variants of `
|
259
|
+
In addition to the evaluation logic, the arrays returned by all variants of `find_*` can be merged:
|
256
260
|
|
257
261
|
```ruby
|
258
262
|
store.find(...) | store.find(...) | store.find(...)
|
@@ -263,8 +267,6 @@ Note that the pipe operator `|` already eliminates duplicates:
|
|
263
267
|
```ruby
|
264
268
|
[a, b, c] | [c, d, e]
|
265
269
|
# => [a, b, c, d, e]
|
266
|
-
# which is equal to
|
267
|
-
([a, b, c] + [c, d, e]).uniq
|
268
270
|
```
|
269
271
|
|
270
272
|
### Serialization
|
data/lib/memstore.rb
CHANGED
@@ -7,11 +7,11 @@ module MemStore
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.from_binary(binary)
|
10
|
-
|
10
|
+
ObjectStore.from_binary(binary)
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.from_file(file)
|
14
|
-
|
14
|
+
ObjectStore.from_file(file)
|
15
15
|
end
|
16
16
|
|
17
17
|
class ObjectStore
|
@@ -29,9 +29,11 @@ module MemStore
|
|
29
29
|
end
|
30
30
|
alias_method :<<, :insert
|
31
31
|
|
32
|
-
def
|
32
|
+
def length
|
33
33
|
@items.length
|
34
34
|
end
|
35
|
+
alias_method :size, :length
|
36
|
+
alias_method :count, :length
|
35
37
|
|
36
38
|
def [](*keys)
|
37
39
|
return @items[keys.first] if keys.length == 1 && !keys.first.is_a?(Range)
|
@@ -103,6 +105,35 @@ module MemStore
|
|
103
105
|
all.detect { |item| instance_exec(item, conditions, block, &FIND_NONE) }
|
104
106
|
end
|
105
107
|
|
108
|
+
def count_all(conditions={}, &block)
|
109
|
+
all.count { |item| instance_exec(item, conditions, block, &FIND_ALL) }
|
110
|
+
end
|
111
|
+
alias_method :count, :count_all
|
112
|
+
|
113
|
+
def count_any(conditions={}, &block)
|
114
|
+
all.count { |item| instance_exec(item, conditions, block, &FIND_ANY) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def count_one(conditions={}, &block)
|
118
|
+
all.count { |item| instance_exec(item, conditions, block, &FIND_ONE) }
|
119
|
+
end
|
120
|
+
|
121
|
+
def count_not_all(conditions={}, &block)
|
122
|
+
all.count { |item| !instance_exec(item, conditions, block, &FIND_ALL) }
|
123
|
+
end
|
124
|
+
|
125
|
+
def count_none(conditions={}, &block)
|
126
|
+
all.count { |item| instance_exec(item, conditions, block, &FIND_NONE) }
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.from_binary(binary)
|
130
|
+
begin Marshal.load(binary) rescue nil end
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.from_file(file)
|
134
|
+
begin self.from_binary(IO.read(file)) rescue nil end
|
135
|
+
end
|
136
|
+
|
106
137
|
def to_binary
|
107
138
|
Marshal.dump(self)
|
108
139
|
end
|
data/lib/memstore/version.rb
CHANGED
data/spec/memstore_spec.rb
CHANGED
@@ -48,19 +48,32 @@ describe MemStore::ObjectStore do
|
|
48
48
|
it "can be converted to and from binary" do
|
49
49
|
o = Dummy.new("custom key")
|
50
50
|
store = MemStore::ObjectStore.new(:id).insert(o)
|
51
|
-
restored = MemStore.from_binary(store.to_binary)
|
51
|
+
restored = MemStore::ObjectStore.from_binary(store.to_binary)
|
52
52
|
restored.must_be_instance_of MemStore::ObjectStore
|
53
53
|
restored.items.must_equal store.items
|
54
54
|
restored.instance_variable_get(:@key).must_equal :id
|
55
55
|
end
|
56
56
|
|
57
|
+
it "returns nil when conversion from binary fails" do
|
58
|
+
MemStore::ObjectStore.from_binary(nil).must_equal nil
|
59
|
+
end
|
60
|
+
|
57
61
|
it "can be serialized to and deserialized from a binary file" do
|
58
62
|
tmp = Tempfile.new("memstore")
|
59
|
-
|
60
|
-
MemStore.
|
63
|
+
o = Dummy.new("custom key")
|
64
|
+
store = MemStore::ObjectStore.new(:id).insert(o)
|
65
|
+
store.to_file(tmp)
|
66
|
+
restored = MemStore::ObjectStore.from_file(tmp)
|
67
|
+
restored.must_be_instance_of MemStore::ObjectStore
|
68
|
+
restored.items.must_equal store.items
|
69
|
+
restored.instance_variable_get(:@key).must_equal :id
|
61
70
|
tmp.unlink
|
62
71
|
end
|
63
72
|
|
73
|
+
it "returns nil when deserialization from binary file fails" do
|
74
|
+
MemStore::ObjectStore.from_file("does_not_exist").must_equal nil
|
75
|
+
end
|
76
|
+
|
64
77
|
end
|
65
78
|
|
66
79
|
describe MemStore::HashStore do
|
@@ -84,9 +97,8 @@ describe MemStore::HashStore do
|
|
84
97
|
end
|
85
98
|
|
86
99
|
it "can be converted to and from binary" do
|
87
|
-
store = MemStore::HashStore.new(:id)
|
88
|
-
|
89
|
-
restored = MemStore.from_binary(store.to_binary)
|
100
|
+
store = MemStore::HashStore.new(:id).insert({ id: "custom key" })
|
101
|
+
restored = MemStore::HashStore.from_binary(store.to_binary)
|
90
102
|
restored.must_be_instance_of MemStore::HashStore
|
91
103
|
restored.items.must_equal store.items
|
92
104
|
restored.instance_variable_get(:@key).must_equal :id
|
@@ -94,8 +106,12 @@ describe MemStore::HashStore do
|
|
94
106
|
|
95
107
|
it "can be serialized to and deserialized from a binary file" do
|
96
108
|
tmp = Tempfile.new("memstore")
|
97
|
-
MemStore::HashStore.new.
|
98
|
-
|
109
|
+
store = MemStore::HashStore.new(:id).insert({ id: "custom key" })
|
110
|
+
store.to_file(tmp)
|
111
|
+
restored = MemStore::HashStore.from_file(tmp)
|
112
|
+
restored.must_be_instance_of MemStore::HashStore
|
113
|
+
restored.items.must_equal store.items
|
114
|
+
restored.instance_variable_get(:@key).must_equal :id
|
99
115
|
tmp.unlink
|
100
116
|
end
|
101
117
|
|
@@ -122,6 +138,10 @@ describe MemStore do
|
|
122
138
|
10.times { |i| @store << i.to_f }
|
123
139
|
end
|
124
140
|
|
141
|
+
it "returns the overall number of items" do
|
142
|
+
@store.length.must_equal 10
|
143
|
+
end
|
144
|
+
|
125
145
|
it "returns a single item by itself" do
|
126
146
|
@store[3].must_equal 3.0
|
127
147
|
end
|
@@ -157,21 +177,6 @@ describe MemStore do
|
|
157
177
|
@store.all.must_equal [0.0, 1.0, 2.0, 7.0, 8.0, 9.0]
|
158
178
|
end
|
159
179
|
|
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
|
174
|
-
|
175
180
|
end
|
176
181
|
|
177
182
|
describe MemStore do
|
@@ -235,4 +240,29 @@ describe MemStore do
|
|
235
240
|
match.id.must_equal 3
|
236
241
|
end
|
237
242
|
|
243
|
+
it "counts all items fulfilling all conditions" do
|
244
|
+
count = @store.count_all(id: 3..7, child: String)
|
245
|
+
count.must_equal [4, 6].length
|
246
|
+
end
|
247
|
+
|
248
|
+
it "counts all items fulfilling at least one condition" do
|
249
|
+
count = @store.count_any(id: 3..7, child: String)
|
250
|
+
count.must_equal [0, 2, 3, 4, 5, 6, 7, 8].length
|
251
|
+
end
|
252
|
+
|
253
|
+
it "counts all items fulfilling exactly one condition" do
|
254
|
+
count = @store.count_one(name: /o/, child: String)
|
255
|
+
count.must_equal [1, 4, 7, 9].length
|
256
|
+
end
|
257
|
+
|
258
|
+
it "counts all items violating at least one condition" do
|
259
|
+
count = @store.count_not_all(name: /o/, child: String)
|
260
|
+
count.must_equal [1, 3, 4, 5, 7, 9].length
|
261
|
+
end
|
262
|
+
|
263
|
+
it "counts all items violating all conditions" do
|
264
|
+
count = @store.count_none(name: /o/, child: String)
|
265
|
+
count.must_equal [3, 5].length
|
266
|
+
end
|
267
|
+
|
238
268
|
end
|