memstore 1.2.0 → 1.2.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/lib/memstore.rb CHANGED
@@ -7,18 +7,22 @@ require "memstore/queries"
7
7
 
8
8
  module MemStore
9
9
 
10
+ # Shortcut to ObjectStore::new
10
11
  def self.new(key=nil, items={})
11
12
  ObjectStore.new(key, items)
12
13
  end
13
14
 
15
+ # Shortcut to ObjectStore::from_binary
14
16
  def self.from_binary(binary)
15
17
  ObjectStore.from_binary(binary)
16
18
  end
17
19
 
20
+ # Shortcut to ObjectStore::from_file
18
21
  def self.from_file(file)
19
22
  ObjectStore.from_file(file)
20
23
  end
21
24
 
25
+ # Shortcut to ObjectStore::with_file
22
26
  def self.with_file(file, key=nil, items={}, &block)
23
27
  ObjectStore.with_file(file, key, items, &block)
24
28
  end
@@ -2,11 +2,61 @@
2
2
 
3
3
  module MemStore
4
4
 
5
+ # A HashStore accesses item attributes through item[attribute].
5
6
  class HashStore < ObjectStore
6
7
 
8
+ # Initializes a HashStore.
9
+ #
10
+ # key - Optional Object used as an item’s key attribute (default: nil).
11
+ # When no key is specified, Object#hash will be used for uniquely identifying items.
12
+ # items - Optional Hash of items to initialize the data store with (default: empty Hash).
13
+ #
14
+ # Examples
15
+ #
16
+ # store = HashStore.new
17
+ # store = HashStore.new(:id)
18
+ # store = HashStore.new(nil, { a.hash => a, b.hash => b, c.hash => c })
19
+ # store = HashStore.new(:id, { 1 => a, 2 => b, 3 => c })
20
+ #
21
+ # Returns initialized ObjectStore.
22
+ def initialize(key=nil, items={})
23
+ @key, @items = key, items
24
+ end
25
+
26
+ # Returns data store as a Hash with the fields :key and :items.
27
+ def to_hash
28
+ { key: @key, items: @items }
29
+ end
30
+
31
+ # Restores a data store from binary format.
32
+ #
33
+ # binary - Binary data containing a serialized instance of HashStore.
34
+ #
35
+ # Examples
36
+ #
37
+ # store = HashStore.from_binary(IO.read(file))
38
+ #
39
+ # Returns instance of HashStore
40
+ # or nil if marshalling failed or marshalled object isn’t a HashStore.
41
+ # Raises whatever Marshal::load raises.
42
+ def self.from_binary(binary)
43
+ restored = Marshal.load(binary) rescue nil
44
+ if restored.instance_of?(HashStore) then restored else nil end
45
+ end
46
+
47
+ # Restores a data store from a Hash.
48
+ #
49
+ # hash - Hash that contains a serialized HashStore.
50
+ # It must have the fields :key/"key" and :items/"items".
51
+ #
52
+ # Examples
53
+ #
54
+ # store = HashStore.from_hash(hash)
55
+ #
56
+ # Returns instance of HashStore
57
+ # or nil if hash isn’t a Hash or doesn’t have the required fields.
7
58
  def self.from_hash(hash)
8
59
  begin
9
-
10
60
  if hash.has_key?(:key) then key = hash[:key]
11
61
  elsif hash.has_key? "key" then key = hash["key"]
12
62
  else return nil end
@@ -16,26 +66,30 @@ module MemStore
16
66
  else return nil end
17
67
 
18
68
  if items.is_a?(Hash) then self.new(key, items) else self.new(key) end
19
-
20
69
  rescue
21
70
  nil
22
71
  end
23
72
  end
24
73
 
25
- def initialize(key=nil, items={})
26
- @key, @items = key, items
27
- end
28
-
29
- def to_hash
30
- { key: @key, items: @items }
31
- end
32
-
33
74
  private
34
75
 
76
+ # Internal: Obtains the key attribute of an item.
77
+ #
78
+ # item - Object that responds to the [] operator (e.g. Hash).
79
+ #
80
+ # Returns result of calling the [] operator with the key attribute on the item.
81
+ # Raises NoMethodError when item does’t respond to the key attribute method.
35
82
  def key(item)
36
83
  if @key.nil? then item.hash else item[@key] end
37
84
  end
38
85
 
86
+ # Internal: Obtains the specified attribute of an item.
87
+ #
88
+ # item - Object that responds to the [] operator (e.g. Hash).
89
+ # attribute - Object used as the attribute key in the item.
90
+ #
91
+ # Returns result of calling the [] operator with the attribute on the item.
92
+ # Raises NoMethodError when item does’t respond to the [] operator.
39
93
  def attr(item, attribute)
40
94
  item[attribute]
41
95
  end
data/lib/memstore/json.rb CHANGED
@@ -23,7 +23,7 @@ module MemStore
23
23
  end
24
24
 
25
25
  def self.with_json_file(file, key=nil, items={}, &block)
26
- self.run_with_file(:from_json_file, :to_json_file, file, key, items, &block)
26
+ self.execute_with_file(:from_json_file, :to_json_file, file, key, items, &block)
27
27
  end
28
28
 
29
29
  end
@@ -23,7 +23,7 @@ module MemStore
23
23
  end
24
24
 
25
25
  def self.with_msgpack_file(file, key=nil, items={}, &block)
26
- self.run_with_file(:from_msgpack_file, :to_msgpack_file, file, key, items, &block)
26
+ self.execute_with_file(:from_msgpack_file, :to_msgpack_file, file, key, items, &block)
27
27
  end
28
28
 
29
29
  end
@@ -2,39 +2,100 @@
2
2
 
3
3
  module MemStore
4
4
 
5
+ # An ObjectStore accesses item attributes through item#attribute.
5
6
  class ObjectStore
6
7
 
8
+ # Initializes an ObjectStore.
9
+ #
10
+ # key - Optional Symbol or String naming the method to obtain an item’s key attribute (default: nil).
11
+ # When no key is specified, Object#hash will be used for uniquely identifying items.
12
+ # items - Optional Hash of items to initialize the data store with (default: empty Hash).
13
+ #
14
+ # Examples
15
+ #
16
+ # store = ObjectStore.new
17
+ # store = ObjectStore.new(:id)
18
+ # store = ObjectStore.new(nil, { a.hash => a, b.hash => b, c.hash => c })
19
+ # store = ObjectStore.new(:id, { 1 => a, 2 => b, 3 => c })
20
+ #
21
+ # Returns initialized ObjectStore.
7
22
  def initialize(key=nil, items={})
8
23
  @key = key || :hash
9
24
  @items = items
10
25
  end
11
26
 
27
+ # Provides access to internal items collection (which is simply a Hash).
12
28
  attr_accessor :items
13
29
 
30
+ # Inserts one or more items into the data store, can be chained.
31
+ # Also available as #<<, which only allows for one item at a time.
32
+ #
33
+ # items - One or more Objects that respond to the method specified as key attribute.
34
+ #
35
+ # Examples
36
+ #
37
+ # store.insert(a).insert(b).insert(c)
38
+ # store.insert(a, b, c)
39
+ # store << a << b << c
40
+ #
41
+ # Returns the data store itself to enable chaining.
42
+ # Raises NoMethodError when an item does’t respond to the key attribute method.
14
43
  def insert(*items)
15
44
  items.each { |item| @items[key(item)] = item }
16
45
  self
17
46
  end
18
47
  alias_method :<<, :insert
19
48
 
49
+ # Returns total number of items in the data store. Also available as #size.
20
50
  def length
21
51
  @items.length
22
52
  end
23
53
  alias_method :size, :length
24
- alias_method :count, :length
25
54
 
55
+ # Retrieves one or more items by key.
56
+ #
57
+ # keys - One or more Objects or Ranges that are keys of items.
58
+ # For a Range, all items with keys in that range are returned.
59
+ #
60
+ # Examples
61
+ #
62
+ # store[1]
63
+ # store[1, 2, 3]
64
+ # store[1..3]
65
+ # store[1, 3..5, 7]
66
+ #
67
+ # Returns an Object if a single key was given
68
+ # or nil if no item with that key exists
69
+ # or an Array of Objects when multiple keys were given
70
+ # in which nil is placed wherever there isn’t an item with that key.
26
71
  def [](*keys)
27
72
  return @items[keys.first] if keys.length == 1 && !keys.first.is_a?(Range)
28
- keys.inject [] do |items, key|
73
+ keys.inject([]) do |items, key|
29
74
  if key.is_a?(Range) then key.inject(items) { |i, k| i << @items[k] }
30
75
  else items << @items[key] end
31
76
  end
32
77
  end
33
78
 
79
+ # Returns all items as an Array.
34
80
  def all
35
81
  @items.values
36
82
  end
37
83
 
84
+ # Deletes one or more items by reference. Also available as #delete_item and #delete.
85
+ #
86
+ # items - One or more Objects that respond to the method specified as key attribute.
87
+ #
88
+ # Examples
89
+ #
90
+ # store.delete_item(a)
91
+ # store.delete_items(a, b, c)
92
+ # store.delete(a)
93
+ # store.delete(a, b, c)
94
+ #
95
+ # Returns the Object that was removed if a single item was given
96
+ # or nil if the item isn’t in the data store
97
+ # or an Array of Objects that were removed when multiple items were given
98
+ # in which nil is placed wherever that item isn’t in the data store.
38
99
  def delete_items(*items)
39
100
  return @items.delete(key(items.first)) if items.length == 1
40
101
  items.collect { |item| @items.delete(key(item)) }
@@ -42,47 +103,147 @@ module MemStore
42
103
  alias_method :delete_item, :delete_items
43
104
  alias_method :delete, :delete_items
44
105
 
106
+ # Deletes one or more items by key. Also available as #delete_key.
107
+ #
108
+ # keys - One or more Objects or Ranges that are keys of items.
109
+ # For a Range, all items with keys in that range are deleted.
110
+ #
111
+ # Examples
112
+ #
113
+ # store.delete_key(1)
114
+ # store.delete_keys(1, 2, 3)
115
+ # store.delete_keys(1..3)
116
+ # store.delete_keys(1, 3..5, 7)
117
+ #
118
+ # Returns the Object that was removed if a single key was given
119
+ # or nil if no item with that key exists
120
+ # or an Array of Objects that were removed when multiple keys were given
121
+ # in which nil is placed wherever there isn’t an item with that key.
45
122
  def delete_keys(*keys)
46
123
  return @items.delete(keys.first) if keys.length == 1 && !keys.first.is_a?(Range)
47
- keys.inject [] do |items, key|
124
+ keys.inject([]) do |items, key|
48
125
  if key.is_a?(Range) then key.inject(items) { |i, k| i << @items.delete(k) }
49
126
  else items << @items.delete(key) end
50
127
  end
51
128
  end
52
129
  alias_method :delete_key, :delete_keys
53
130
 
54
- def self.from_binary(binary)
55
- restored = Marshal.load(binary) rescue nil
56
- if restored.kind_of?(ObjectStore) || restored.kind_of?(HashStore) then restored else nil end
57
- end
58
-
59
- def self.from_file(file)
60
- self.from_binary(IO.read(file)) rescue nil
61
- end
62
-
131
+ # Returns data store in binary format.
132
+ # Raises whatever Marshal::dump raises.
63
133
  def to_binary
64
134
  Marshal.dump(self)
65
135
  end
66
136
 
137
+ # Writes data store to a file in binary format.
138
+ #
139
+ # file - IO stream of file name as String.
140
+ #
141
+ # Returns number of bytes that were written to the file.
142
+ # Raises whatever IO::write raises.
67
143
  def to_file(file)
68
144
  IO.write(file, self.to_binary)
69
145
  end
70
146
 
147
+ # Restores a data store from binary format.
148
+ #
149
+ # binary - Binary data containing a serialized instance of ObjectStore.
150
+ #
151
+ # Examples
152
+ #
153
+ # store = ObjectStore.from_binary(IO.read(file))
154
+ #
155
+ # Returns instance of ObjectStore
156
+ # or nil if marshalling failed or marshalled object isn’t an ObjectStore.
157
+ # Raises whatever Marshal::load raises.
158
+ def self.from_binary(binary)
159
+ restored = Marshal.load(binary) rescue nil
160
+ if restored.instance_of?(ObjectStore) then restored else nil end
161
+ end
162
+
163
+ # Restores a data store from a binary file.
164
+ #
165
+ # file - IO stream or file name as String.
166
+ #
167
+ # Examples
168
+ #
169
+ # store = ObjectStore.from_file(file)
170
+ #
171
+ # Returns instance of ObjectStore or nil (result of ::from_binary)
172
+ # or nil if file IO failed, e.g. because file doesn’t exist or isn’t readable.
173
+ # Raises whatever IO::read or Marshal::load raise.
174
+ def self.from_file(file)
175
+ self.from_binary(IO.read(file)) rescue nil
176
+ end
177
+
178
+ # Executes a given block while keeping an exclusive lock on a file.
179
+ # Allows to use the same file for persistence from multiple threads/processes.
180
+ # Tries to deserialize a data store from the file using ::from_file.
181
+ # If that fails, a new one will be created using the supplied key and items.
182
+ # Writes data store back to file using #to_file after block returns.
183
+ #
184
+ # file - IO stream or file name as String.
185
+ # key - Optional key attribute (Symbol or String) to use in ::new (default: nil).
186
+ # items - Optional items Hash to use in ::new (default: empty Hash).
187
+ # block - Block that will be called after a data store was restored or created.
188
+ #
189
+ # Yields the restored or newly created data store.
190
+ #
191
+ # Examples
192
+ #
193
+ # size_after_changes = ObjectStore.with_file(file, :id) do |store|
194
+ # store.delete(a, b, c, d, e)
195
+ # store.insert(f, g, h)
196
+ # store.size
197
+ # end
198
+ #
199
+ # Returns whatever the block returns.
200
+ # Raises whatever File::open, IO::read, Marshal::load, Marshal::dump or IO::write raise.
71
201
  def self.with_file(file, key=nil, items={}, &block)
72
- self.run_with_file(:from_file, :to_file, file, key, items, &block)
202
+ self.execute_with_file(:from_file, :to_file, file, key, items, &block)
73
203
  end
74
204
 
75
205
  private
76
206
 
207
+ # Internal: Obtains the key attribute of an item.
208
+ #
209
+ # item - Object that responds to the attribute.
210
+ #
211
+ # Returns result of calling the key attribute method on the item.
212
+ # Raises NoMethodError when item does’t respond to the key attribute method.
77
213
  def key(item)
78
214
  item.send(@key)
79
215
  end
80
216
 
217
+ # Internal: Obtains the specified attribute of an item.
218
+ #
219
+ # item - Object that responds to the attribute.
220
+ # attribute - Symbol or String naming the attribute.
221
+ #
222
+ # Returns result of calling the attribute method on the item.
223
+ # Raises NoMethodError when item does’t respond to the attribute method.
81
224
  def attr(item, attribute)
82
225
  item.send(attribute)
83
226
  end
84
227
 
85
- def self.run_with_file(from_file_method, to_file_method, file, key=nil, items={}, &block)
228
+ # Internal: Used to implement with_file and variants for different formats/subclasses.
229
+ # Takes required method names, can therefore be used by any subclass.
230
+ # Executes a given block while keeping an exclusive lock on a file.
231
+ # Tries to deserialize a data store from the file using from_file_method.
232
+ # If that fails, a new one will be created using the supplied key and items.
233
+ # Writes data store back to file using to_file_method after block returns.
234
+ #
235
+ # from_file_method - Name of class method (Symbol or String) to deserialize data store from file.
236
+ # to_file_method - Name of instance method (Symbol or String) to serialize data store to file.
237
+ # file - IO stream or file name as String.
238
+ # key - Optional key attribute (Symbol or String) to use in ::new (default: nil).
239
+ # items - Optional items Hash to use in ::new (default: empty Hash).
240
+ # block - Block that will be called after a data store was restored or created.
241
+ #
242
+ # Yields the restored or newly created data store.
243
+ #
244
+ # Returns whatever the block returns.
245
+ # Raises whatever File::open, IO::read, Marshal::load, Marshal::dump or IO::write raise.
246
+ def self.execute_with_file(from_file_method, to_file_method, file, key=nil, items={}, &block)
86
247
  File.open(file) do |file|
87
248
  file.flock(File::LOCK_EX)
88
249
  store = self.send(from_file_method, file) || self.new(key, items)
@@ -4,91 +4,141 @@ module MemStore
4
4
 
5
5
  class ObjectStore
6
6
 
7
+ # All methods have the following signature:
8
+ #
9
+ # conditions - Hash mapping attributes to conditions.
10
+ # Attributes can be Symbols or String for ObjectStore
11
+ # and any kind of Object for HashStore.
12
+ # Conditions can be any kind of Object that responds to #===.
13
+ # block - Optional block taking an item and returning a bool indicating
14
+ # whether the item passed the tests within the block.
15
+ #
16
+ # Yields every item in the data store after the conditions were evaluated for it.
17
+
18
+ ### find ###
19
+
20
+ # Also available as #find.
21
+ # Returns an Array of items that fulfill all conditions.
7
22
  def find_all(conditions={}, &block)
8
23
  all.select { |item| instance_exec(item, conditions, block, &FIND_ALL) }
9
24
  end
10
25
  alias_method :find, :find_all
11
26
 
27
+ # Returns an Array of items that fulfill at least one condition.
12
28
  def find_any(conditions={}, &block)
13
29
  all.select { |item| instance_exec(item, conditions, block, &FIND_ANY) }
14
30
  end
15
31
 
32
+ # Returns an Array of items that fulfill exactly one condition.
16
33
  def find_one(conditions={}, &block)
17
34
  all.select { |item| instance_exec(item, conditions, block, &FIND_ONE) }
18
35
  end
19
36
 
37
+ # Returns an Array of items that violate at least one condition.
20
38
  def find_not_all(conditions={}, &block)
21
39
  all.reject { |item| instance_exec(item, conditions, block, &FIND_ALL) }
22
40
  end
23
41
 
42
+ # Returns an Array of items that violate all conditions.
24
43
  def find_none(conditions={}, &block)
25
44
  all.select { |item| instance_exec(item, conditions, block, &FIND_NONE) }
26
45
  end
27
46
 
47
+ ### first ###
48
+
49
+ # Also available as #first.
50
+ # Returns the first item that fulfills all conditions.
28
51
  def first_all(conditions={}, &block)
29
52
  all.detect { |item| instance_exec(item, conditions, block, &FIND_ALL) }
30
53
  end
31
54
  alias_method :first, :first_all
32
55
 
56
+ # Returns the first item that fulfills at least one condition.
33
57
  def first_any(conditions={}, &block)
34
58
  all.detect { |item| instance_exec(item, conditions, block, &FIND_ANY) }
35
59
  end
36
60
 
61
+ # Returns the first item that fulfills exactly one condition.
37
62
  def first_one(conditions={}, &block)
38
63
  all.detect { |item| instance_exec(item, conditions, block, &FIND_ONE) }
39
64
  end
40
65
 
66
+ # which is equivalent to: !condition || !condition || ... [|| !block]
67
+ # Returns the first item that violates at least one condition.
41
68
  def first_not_all(conditions={}, &block)
42
69
  all.detect { |item| !instance_exec(item, conditions, block, &FIND_ALL) }
43
70
  end
44
71
 
72
+ # Returns the first item that violates all conditions.
45
73
  def first_none(conditions={}, &block)
46
74
  all.detect { |item| instance_exec(item, conditions, block, &FIND_NONE) }
47
75
  end
48
76
 
77
+ ### count ###
78
+
79
+ # Also available as #count.
80
+ # Returns the number of items that fulfill all conditions.
49
81
  def count_all(conditions={}, &block)
50
82
  all.count { |item| instance_exec(item, conditions, block, &FIND_ALL) }
51
83
  end
52
84
  alias_method :count, :count_all
53
85
 
86
+ # Returns the number of items that fulfill at least one condition.
54
87
  def count_any(conditions={}, &block)
55
88
  all.count { |item| instance_exec(item, conditions, block, &FIND_ANY) }
56
89
  end
57
90
 
91
+ # Returns the number of items that fulfill exactly one condition.
58
92
  def count_one(conditions={}, &block)
59
93
  all.count { |item| instance_exec(item, conditions, block, &FIND_ONE) }
60
94
  end
61
95
 
96
+ # which is equivalent to: !condition || !condition || ... [|| !block]
97
+ # Returns the number of items that violate at least one condition.
62
98
  def count_not_all(conditions={}, &block)
63
99
  all.count { |item| !instance_exec(item, conditions, block, &FIND_ALL) }
64
100
  end
65
101
 
102
+ # Returns the number of items that violate all conditions.
66
103
  def count_none(conditions={}, &block)
67
104
  all.count { |item| instance_exec(item, conditions, block, &FIND_NONE) }
68
105
  end
69
106
 
70
107
  private
71
-
108
+
109
+ # All blocks have the following signature:
110
+ #
111
+ # item - The item (Object for ObjectStore, Hash for HashStore) to be tested.
112
+ # conditions - Hash of conditions to be evaluated.
113
+ # block - Optional block that can test the item after the conditions are evaluated.
114
+ #
115
+ # Returns a bool indicating whether the item was a match
116
+ # for the given conditions and matching logic.
117
+
118
+ # Internal: Evaluates conditions using AND, i.e. condition && condition && ... [&& block]
72
119
  FIND_ALL = Proc.new do |item, conditions, block|
73
120
  conditions.all? { |attribute, condition| condition === attr(item, attribute) } &&
74
121
  if block then !!block.call(item) else true end
75
122
  end
76
123
 
124
+ # Internal: Evaluates conditions using OR, i.e. condition || condition || ... [|| block]
77
125
  FIND_ANY = Proc.new do |item, conditions, block|
78
126
  conditions.any? { |attribute, condition| condition === attr(item, attribute) } ||
79
127
  if block then !!block.call(item) else false end
80
128
  end
81
129
 
82
- FIND_NONE = Proc.new do |item, conditions, block|
83
- conditions.none? { |attribute, condition| condition === attr(item, attribute) } &&
84
- if block then !!block.call(item) else true end
85
- end
86
-
130
+ # Internal: Evaluates conditions using XOR, i.e. condition ^ condition ^ condition ... [^ block]
87
131
  FIND_ONE = Proc.new do |item, conditions, block|
88
- conditions.one? { |attribute, condition| condition === attr(item, attribute) } ||
132
+ conditions.one? { |attribute, condition| condition === attr(item, attribute) } ^
89
133
  if block then !!block.call(item) else false end
90
134
  end
91
135
 
136
+ # Internal: Evaluates condition using AND NOT, i.e. !condition && !condition && ... [&& !block]
137
+ FIND_NONE = Proc.new do |item, conditions, block|
138
+ conditions.none? { |attribute, condition| condition === attr(item, attribute) } &&
139
+ if block then !!!block.call(item) else true end
140
+ end
141
+
92
142
  end
93
143
 
94
144
  end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module MemStore
2
- VERSION = "1.2.0"
4
+ VERSION = "1.2.1"
3
5
  end
data/lib/memstore/yaml.rb CHANGED
@@ -27,7 +27,7 @@ module MemStore
27
27
  end
28
28
 
29
29
  def self.with_yaml_file(file, key=nil, items={}, &block)
30
- self.run_with_file(:from_yaml_file, :to_yaml_file, file, key, items, &block)
30
+ self.execute_with_file(:from_yaml_file, :to_yaml_file, file, key, items, &block)
31
31
  end
32
32
 
33
33
  end
@@ -34,6 +34,15 @@ describe MemStore::HashStore do
34
34
  restored.instance_variable_get(:@key).must_equal @store.instance_variable_get(:@key)
35
35
  end
36
36
 
37
+ it "returns nil when conversion from binary fails" do
38
+ MemStore::HashStore.from_binary(nil).must_equal nil
39
+ MemStore::HashStore.from_binary(Marshal.dump(Object.new)).must_equal nil
40
+ end
41
+
42
+ it "returns nil when marshalled object isn’t instance of HashStore" do
43
+ MemStore::HashStore.from_binary(MemStore::ObjectStore.new.to_binary).must_equal nil
44
+ end
45
+
37
46
  it "can be serialized to and deserialized from a binary file" do
38
47
  tmp = Tempfile.new("memstore")
39
48
  @store.to_file(tmp)
@@ -82,6 +82,10 @@ describe MemStore::ObjectStore do
82
82
  MemStore::ObjectStore.from_binary(Marshal.dump(Object.new)).must_equal nil
83
83
  end
84
84
 
85
+ it "returns nil when marshalled object isn’t instance of ObjectStore" do
86
+ MemStore::ObjectStore.from_binary(MemStore::HashStore.new.to_binary).must_equal nil
87
+ end
88
+
85
89
  it "can be serialized to and deserialized from a binary file" do
86
90
  tmp = Tempfile.new("memstore")
87
91
  @store.to_file(tmp)
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.2.0
4
+ version: 1.2.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-20 00:00:00.000000000 Z
12
+ date: 2013-02-21 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.