memstore 1.2.1 → 2.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.
@@ -1,99 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module MemStore
4
-
5
- # A HashStore accesses item attributes through item[attribute].
6
- class HashStore < ObjectStore
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.
58
- def self.from_hash(hash)
59
- begin
60
- if hash.has_key?(:key) then key = hash[:key]
61
- elsif hash.has_key? "key" then key = hash["key"]
62
- else return nil end
63
-
64
- if hash.has_key?(:items) then items = hash[:items]
65
- elsif hash.has_key? "items" then items = hash["items"]
66
- else return nil end
67
-
68
- if items.is_a?(Hash) then self.new(key, items) else self.new(key) end
69
- rescue
70
- nil
71
- end
72
- end
73
-
74
- private
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.
82
- def key(item)
83
- if @key.nil? then item.hash else item[@key] end
84
- end
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.
93
- def attr(item, attribute)
94
- item[attribute]
95
- end
96
-
97
- end
98
-
99
- end
data/lib/memstore/json.rb DELETED
@@ -1,31 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require "json"
4
-
5
- module MemStore
6
-
7
- class HashStore
8
-
9
- def to_json
10
- self.to_hash.to_json
11
- end
12
-
13
- def to_json_file(file)
14
- IO.write(file, self.to_json)
15
- end
16
-
17
- def self.from_json(json)
18
- self.from_hash(JSON.parse(json)) rescue nil
19
- end
20
-
21
- def self.from_json_file(file)
22
- self.from_json(IO.read(file)) rescue nil
23
- end
24
-
25
- def self.with_json_file(file, key=nil, items={}, &block)
26
- self.execute_with_file(:from_json_file, :to_json_file, file, key, items, &block)
27
- end
28
-
29
- end
30
-
31
- end
@@ -1,31 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require "msgpack"
4
-
5
- module MemStore
6
-
7
- class HashStore
8
-
9
- def to_msgpack
10
- self.to_hash.to_msgpack
11
- end
12
-
13
- def to_msgpack_file(file)
14
- IO.write(file, self.to_msgpack)
15
- end
16
-
17
- def self.from_msgpack(msgpack)
18
- self.from_hash(MessagePack.unpack(msgpack)) rescue nil
19
- end
20
-
21
- def self.from_msgpack_file(file)
22
- self.from_msgpack(IO.read(file)) rescue nil
23
- end
24
-
25
- def self.with_msgpack_file(file, key=nil, items={}, &block)
26
- self.execute_with_file(:from_msgpack_file, :to_msgpack_file, file, key, items, &block)
27
- end
28
-
29
- end
30
-
31
- end
@@ -1,259 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module MemStore
4
-
5
- # An ObjectStore accesses item attributes through item#attribute.
6
- class ObjectStore
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.
22
- def initialize(key=nil, items={})
23
- @key = key || :hash
24
- @items = items
25
- end
26
-
27
- # Provides access to internal items collection (which is simply a Hash).
28
- attr_accessor :items
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.
43
- def insert(*items)
44
- items.each { |item| @items[key(item)] = item }
45
- self
46
- end
47
- alias_method :<<, :insert
48
-
49
- # Returns total number of items in the data store. Also available as #size.
50
- def length
51
- @items.length
52
- end
53
- alias_method :size, :length
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.
71
- def [](*keys)
72
- return @items[keys.first] if keys.length == 1 && !keys.first.is_a?(Range)
73
- keys.inject([]) do |items, key|
74
- if key.is_a?(Range) then key.inject(items) { |i, k| i << @items[k] }
75
- else items << @items[key] end
76
- end
77
- end
78
-
79
- # Returns all items as an Array.
80
- def all
81
- @items.values
82
- end
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.
99
- def delete_items(*items)
100
- return @items.delete(key(items.first)) if items.length == 1
101
- items.collect { |item| @items.delete(key(item)) }
102
- end
103
- alias_method :delete_item, :delete_items
104
- alias_method :delete, :delete_items
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.
122
- def delete_keys(*keys)
123
- return @items.delete(keys.first) if keys.length == 1 && !keys.first.is_a?(Range)
124
- keys.inject([]) do |items, key|
125
- if key.is_a?(Range) then key.inject(items) { |i, k| i << @items.delete(k) }
126
- else items << @items.delete(key) end
127
- end
128
- end
129
- alias_method :delete_key, :delete_keys
130
-
131
- # Returns data store in binary format.
132
- # Raises whatever Marshal::dump raises.
133
- def to_binary
134
- Marshal.dump(self)
135
- end
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.
143
- def to_file(file)
144
- IO.write(file, self.to_binary)
145
- end
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.
201
- def self.with_file(file, key=nil, items={}, &block)
202
- self.execute_with_file(:from_file, :to_file, file, key, items, &block)
203
- end
204
-
205
- private
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.
213
- def key(item)
214
- item.send(@key)
215
- end
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.
224
- def attr(item, attribute)
225
- item.send(attribute)
226
- end
227
-
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)
247
- File.open(file) do |file|
248
- file.flock(File::LOCK_EX)
249
- store = self.send(from_file_method, file) || self.new(key, items)
250
- result = block.call(store)
251
- store.send(to_file_method, file)
252
- file.flock(File::LOCK_UN)
253
- result
254
- end
255
- end
256
-
257
- end
258
-
259
- end
data/lib/memstore/yaml.rb DELETED
@@ -1,35 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require "yaml"
4
-
5
- module MemStore
6
-
7
- class HashStore
8
-
9
- def to_yaml
10
- self.to_hash.to_yaml
11
- end
12
-
13
- def to_yaml_file(file)
14
- IO.write(file, self.to_yaml)
15
- end
16
-
17
- def self.from_yaml(yaml)
18
- begin
19
- self.from_hash(YAML.load(yaml))
20
- rescue StandardError, Psych::SyntaxError
21
- nil
22
- end
23
- end
24
-
25
- def self.from_yaml_file(file)
26
- self.from_yaml(IO.read(file)) rescue nil
27
- end
28
-
29
- def self.with_yaml_file(file, key=nil, items={}, &block)
30
- self.execute_with_file(:from_yaml_file, :to_yaml_file, file, key, items, &block)
31
- end
32
-
33
- end
34
-
35
- end