memstore 1.2.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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