memstore 1.0.1 → 1.1.0

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
@@ -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.size
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 age: [23, 25, 27]
249
+ store.find(age: [23, 25, 27])
246
250
  ```
247
251
 
248
- The block is invoked with every item and can do more complex tests.
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 `find` can be merged:
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
- begin Marshal.load(binary) rescue nil end
10
+ ObjectStore.from_binary(binary)
11
11
  end
12
12
 
13
13
  def self.from_file(file)
14
- begin self.from_binary(IO.read(file)) rescue nil end
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 size
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
@@ -1,3 +1,3 @@
1
1
  module MemStore
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -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
- MemStore::ObjectStore.new.to_file tmp
60
- MemStore.from_file(tmp).must_be_instance_of MemStore::ObjectStore
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
- 10.times { |i| store << { id: i } }
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.to_file tmp
98
- MemStore.from_file(tmp).must_be_instance_of MemStore::HashStore
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
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.1
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: