pstore 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64e6beb51b67d033d9cafd55c6a77e4d9a9ea463797420bb2bb445fd46809247
4
- data.tar.gz: fdf667f2db6f758970ec437f896ce0a2c529cb16dcf6853c77a8778427b455ad
3
+ metadata.gz: 4ca86b8693a69b67fa1864f055fb547d881d62979a047a7fa24e43aa0688cc01
4
+ data.tar.gz: b4af87cbe5e36edcf852c5465e686e477cb8ae301cd00c4dd8a38f56aa23f6e2
5
5
  SHA512:
6
- metadata.gz: 42aa9cc162c121889583174d1d45878c7aad794b21e56bbdd6c12789e74e0ea9adfd3a5d73ead981121b32594b7c06ce94a5c4265da47ce3c212c1e63d311c84
7
- data.tar.gz: e13b2a5b4a947940044372028499f9af004239aa043218fb0397200c5ade08cad39d4fede8198291de77d7b15a9cca1802e9ef681ca4d3f8f6562956e65828bc
6
+ metadata.gz: 8f87e2b27466bcb3dfb2b910b1fb2fafcec06beef6d4aa49c9dad2acdf170c9d5db8631b9c08097b97334ec3797043c89b96b138c363805205407d0cc0b08590
7
+ data.tar.gz: 0efcfca9e94dae981be03cfd191265d10c348241b243c2fd7f7ae0fa07b63781ddcf70853dea07889294fd85794fbbc34f7b00b2de67de2b16950b882fe302f2
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'weekly'
@@ -11,14 +11,12 @@ jobs:
11
11
  os: [ ubuntu-latest, macos-latest ]
12
12
  runs-on: ${{ matrix.os }}
13
13
  steps:
14
- - uses: actions/checkout@master
14
+ - uses: actions/checkout@v3
15
15
  - name: Set up Ruby
16
16
  uses: ruby/setup-ruby@v1
17
17
  with:
18
18
  ruby-version: ${{ matrix.ruby }}
19
19
  - name: Install dependencies
20
- run: |
21
- gem install bundler --no-document
22
- bundle install
20
+ run: bundle install
23
21
  - name: Run test
24
22
  run: rake test
data/Rakefile CHANGED
@@ -7,4 +7,11 @@ Rake::TestTask.new(:test) do |t|
7
7
  t.test_files = FileList["test/**/test_*.rb"]
8
8
  end
9
9
 
10
+ task :sync_tool do
11
+ require 'fileutils'
12
+ FileUtils.cp "../ruby/tool/lib/core_assertions.rb", "./test/lib"
13
+ FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib"
14
+ FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib"
15
+ end
16
+
10
17
  task :default => :test
data/lib/pstore.rb CHANGED
@@ -10,89 +10,323 @@
10
10
 
11
11
  require "digest"
12
12
 
13
- #
14
- # PStore implements a file based persistence mechanism based on a Hash. User
15
- # code can store hierarchies of Ruby objects (values) into the data store file
16
- # by name (keys). An object hierarchy may be just a single object. User code
17
- # may later read values back from the data store or even update data, as needed.
13
+ # \PStore implements a file based persistence mechanism based on a Hash.
14
+ # User code can store hierarchies of Ruby objects (values)
15
+ # into the data store by name (keys).
16
+ # An object hierarchy may be just a single object.
17
+ # User code may later read values back from the data store
18
+ # or even update data, as needed.
18
19
  #
19
20
  # The transactional behavior ensures that any changes succeed or fail together.
20
- # This can be used to ensure that the data store is not left in a transitory
21
- # state, where some values were updated but others were not.
21
+ # This can be used to ensure that the data store is not left in a transitory state,
22
+ # where some values were updated but others were not.
23
+ #
24
+ # Behind the scenes, Ruby objects are stored to the data store file with Marshal.
25
+ # That carries the usual limitations. Proc objects cannot be marshalled,
26
+ # for example.
27
+ #
28
+ # There are three important concepts here (details at the links):
29
+ #
30
+ # - {Store}[rdoc-ref:PStore@The+Store]: a store is an instance of \PStore.
31
+ # - {Entries}[rdoc-ref:PStore@Entries]: the store is hash-like;
32
+ # each entry is the key for a stored object.
33
+ # - {Transactions}[rdoc-ref:PStore@Transactions]: each transaction is a collection
34
+ # of prospective changes to the store;
35
+ # a transaction is defined in the block given with a call
36
+ # to PStore#transaction.
37
+ #
38
+ # == About the Examples
39
+ #
40
+ # Examples on this page need a store that has known properties.
41
+ # They can get a new (and populated) store by calling thus:
42
+ #
43
+ # example_store do |store|
44
+ # # Example code using store goes here.
45
+ # end
46
+ #
47
+ # All we really need to know about +example_store+
48
+ # is that it yields a fresh store with a known population of entries;
49
+ # its implementation:
50
+ #
51
+ # require 'pstore'
52
+ # require 'tempfile'
53
+ # # Yield a pristine store for use in examples.
54
+ # def example_store
55
+ # # Create the store in a temporary file.
56
+ # Tempfile.create do |file|
57
+ # store = PStore.new(file)
58
+ # # Populate the store.
59
+ # store.transaction do
60
+ # store[:foo] = 0
61
+ # store[:bar] = 1
62
+ # store[:baz] = 2
63
+ # end
64
+ # yield store
65
+ # end
66
+ # end
67
+ #
68
+ # == The Store
69
+ #
70
+ # The contents of the store are maintained in a file whose path is specified
71
+ # when the store is created (see PStore.new).
72
+ # The objects are stored and retrieved using
73
+ # module Marshal, which means that certain objects cannot be added to the store;
74
+ # see {Marshal::dump}[https://docs.ruby-lang.org/en/master/Marshal.html#method-c-dump].
75
+ #
76
+ # == Entries
77
+ #
78
+ # A store may have any number of entries.
79
+ # Each entry has a key and a value, just as in a hash:
80
+ #
81
+ # - Key: as in a hash, the key can be (almost) any object;
82
+ # see {Hash Keys}[https://docs.ruby-lang.org/en/master/Hash.html#class-Hash-label-Hash+Keys].
83
+ # You may find it convenient to keep it simple by using only
84
+ # symbols or strings as keys.
85
+ # - Value: the value may be any object that can be marshalled by \Marshal
86
+ # (see {Marshal::dump}[https://docs.ruby-lang.org/en/master/Marshal.html#method-c-dump])
87
+ # and in fact may be a collection
88
+ # (e.g., an array, a hash, a set, a range, etc).
89
+ # That collection may in turn contain nested objects,
90
+ # including collections, to any depth;
91
+ # those objects must also be \Marshal-able.
92
+ # See {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
93
+ #
94
+ # == Transactions
95
+ #
96
+ # === The Transaction Block
97
+ #
98
+ # The block given with a call to method #transaction#
99
+ # contains a _transaction_,
100
+ # which consists of calls to \PStore methods that
101
+ # read from or write to the store
102
+ # (that is, all \PStore methods except #transaction itself,
103
+ # #path, and Pstore.new):
104
+ #
105
+ # example_store do |store|
106
+ # store.transaction do
107
+ # store.keys # => [:foo, :bar, :baz]
108
+ # store[:bat] = 3
109
+ # store.keys # => [:foo, :bar, :baz, :bat]
110
+ # end
111
+ # end
112
+ #
113
+ # Execution of the transaction is deferred until the block exits,
114
+ # and is executed _atomically_ (all-or-nothing):
115
+ # either all transaction calls are executed, or none are.
116
+ # This maintains the integrity of the store.
117
+ #
118
+ # Other code in the block (including even calls to #path and PStore.new)
119
+ # is executed immediately, not deferred.
120
+ #
121
+ # The transaction block:
122
+ #
123
+ # - May not contain a nested call to #transaction.
124
+ # - Is the only context where methods that read from or write to
125
+ # the store are allowed.
126
+ #
127
+ # As seen above, changes in a transaction are made automatically
128
+ # when the block exits.
129
+ # The block may be exited early by calling method #commit or #abort.
130
+ #
131
+ # - Method #commit triggers the update to the store and exits the block:
132
+ #
133
+ # example_store do |store|
134
+ # store.transaction do
135
+ # store.keys # => [:foo, :bar, :baz]
136
+ # store[:bat] = 3
137
+ # store.commit
138
+ # fail 'Cannot get here'
139
+ # end
140
+ # store.transaction do
141
+ # # Update was completed.
142
+ # store.keys # => [:foo, :bar, :baz, :bat]
143
+ # end
144
+ # end
145
+ #
146
+ # - Method #abort discards the update to the store and exits the block:
147
+ #
148
+ # example_store do |store|
149
+ # store.transaction do
150
+ # store.keys # => [:foo, :bar, :baz]
151
+ # store[:bat] = 3
152
+ # store.abort
153
+ # fail 'Cannot get here'
154
+ # end
155
+ # store.transaction do
156
+ # # Update was not completed.
157
+ # store.keys # => [:foo, :bar, :baz]
158
+ # end
159
+ # end
160
+ #
161
+ # === Read-Only Transactions
162
+ #
163
+ # By default, a transaction allows both reading from and writing to
164
+ # the store:
165
+ #
166
+ # store.transaction do
167
+ # # Read-write transaction.
168
+ # # Any code except a call to #transaction is allowed here.
169
+ # end
170
+ #
171
+ # If argument +read_only+ is passed as +true+,
172
+ # only reading is allowed:
173
+ #
174
+ # store.transaction(true) do
175
+ # # Read-only transaction:
176
+ # # Calls to #transaction, #[]=, and #delete are not allowed here.
177
+ # end
178
+ #
179
+ # == Hierarchical Values
180
+ #
181
+ # The value for an entry may be a simple object (as seen above).
182
+ # It may also be a hierarchy of objects nested to any depth:
183
+ #
184
+ # deep_store = PStore.new('deep.store')
185
+ # deep_store.transaction do
186
+ # array_of_hashes = [{}, {}, {}]
187
+ # deep_store[:array_of_hashes] = array_of_hashes
188
+ # deep_store[:array_of_hashes] # => [{}, {}, {}]
189
+ # hash_of_arrays = {foo: [], bar: [], baz: []}
190
+ # deep_store[:hash_of_arrays] = hash_of_arrays
191
+ # deep_store[:hash_of_arrays] # => {:foo=>[], :bar=>[], :baz=>[]}
192
+ # deep_store[:hash_of_arrays][:foo].push(:bat)
193
+ # deep_store[:hash_of_arrays] # => {:foo=>[:bat], :bar=>[], :baz=>[]}
194
+ # end
195
+ #
196
+ # And recall that you can use
197
+ # {dig methods}[https://docs.ruby-lang.org/en/master/dig_methods_rdoc.html]
198
+ # in a returned hierarchy of objects.
199
+ #
200
+ # == Working with the Store
201
+ #
202
+ # === Creating a Store
203
+ #
204
+ # Use method PStore.new to create a store.
205
+ # The new store creates or opens its containing file:
206
+ #
207
+ # store = PStore.new('t.store')
208
+ #
209
+ # === Modifying the Store
210
+ #
211
+ # Use method #[]= to update or create an entry:
212
+ #
213
+ # example_store do |store|
214
+ # store.transaction do
215
+ # store[:foo] = 1 # Update.
216
+ # store[:bam] = 1 # Create.
217
+ # end
218
+ # end
219
+ #
220
+ # Use method #delete to remove an entry:
221
+ #
222
+ # example_store do |store|
223
+ # store.transaction do
224
+ # store.delete(:foo)
225
+ # store[:foo] # => nil
226
+ # end
227
+ # end
228
+ #
229
+ # === Retrieving Values
230
+ #
231
+ # Use method #fetch (allows default) or #[] (defaults to +nil+)
232
+ # to retrieve an entry:
233
+ #
234
+ # example_store do |store|
235
+ # store.transaction do
236
+ # store[:foo] # => 0
237
+ # store[:nope] # => nil
238
+ # store.fetch(:baz) # => 2
239
+ # store.fetch(:nope, nil) # => nil
240
+ # store.fetch(:nope) # Raises exception.
241
+ # end
242
+ # end
243
+ #
244
+ # === Querying the Store
245
+ #
246
+ # Use method #key? to determine whether a given key exists:
22
247
  #
23
- # Behind the scenes, Ruby objects are stored to the data store file with
24
- # Marshal. That carries the usual limitations. Proc objects cannot be
25
- # marshalled, for example.
248
+ # example_store do |store|
249
+ # store.transaction do
250
+ # store.key?(:foo) # => true
251
+ # end
252
+ # end
26
253
  #
27
- # == Usage example:
254
+ # Use method #keys to retrieve keys:
255
+ #
256
+ # example_store do |store|
257
+ # store.transaction do
258
+ # store.keys # => [:foo, :bar, :baz]
259
+ # end
260
+ # end
261
+ #
262
+ # Use method #path to retrieve the path to the store's underlying file;
263
+ # this method may be called from outside a transaction block:
264
+ #
265
+ # store = PStore.new('t.store')
266
+ # store.path # => "t.store"
267
+ #
268
+ # == Transaction Safety
269
+ #
270
+ # For transaction safety, see:
271
+ #
272
+ # - Optional argument +thread_safe+ at method PStore.new.
273
+ # - Attribute #ultra_safe.
274
+ #
275
+ # Needless to say, if you're storing valuable data with \PStore, then you should
276
+ # backup the \PStore file from time to time.
277
+ #
278
+ # == An Example Store
28
279
  #
29
280
  # require "pstore"
30
281
  #
31
- # # a mock wiki object...
282
+ # # A mock wiki object.
32
283
  # class WikiPage
33
- # def initialize( page_name, author, contents )
284
+ #
285
+ # attr_reader :page_name
286
+ #
287
+ # def initialize(page_name, author, contents)
34
288
  # @page_name = page_name
35
289
  # @revisions = Array.new
36
- #
37
290
  # add_revision(author, contents)
38
291
  # end
39
292
  #
40
- # attr_reader :page_name
41
- #
42
- # def add_revision( author, contents )
43
- # @revisions << { :created => Time.now,
44
- # :author => author,
45
- # :contents => contents }
293
+ # def add_revision(author, contents)
294
+ # @revisions << {created: Time.now,
295
+ # author: author,
296
+ # contents: contents}
46
297
  # end
47
298
  #
48
299
  # def wiki_page_references
49
300
  # [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/)
50
301
  # end
51
302
  #
52
- # # ...
53
303
  # end
54
304
  #
55
- # # create a new page...
56
- # home_page = WikiPage.new( "HomePage", "James Edward Gray II",
57
- # "A page about the JoysOfDocumentation..." )
305
+ # # Create a new wiki page.
306
+ # home_page = WikiPage.new("HomePage", "James Edward Gray II",
307
+ # "A page about the JoysOfDocumentation..." )
58
308
  #
59
- # # then we want to update page data and the index together, or not at all...
60
309
  # wiki = PStore.new("wiki_pages.pstore")
61
- # wiki.transaction do # begin transaction; do all of this or none of it
62
- # # store page...
310
+ # # Update page data and the index together, or not at all.
311
+ # wiki.transaction do
312
+ # # Store page.
63
313
  # wiki[home_page.page_name] = home_page
64
- # # ensure that an index has been created...
314
+ # # Create page index.
65
315
  # wiki[:wiki_index] ||= Array.new
66
- # # update wiki index...
316
+ # # Update wiki index.
67
317
  # wiki[:wiki_index].push(*home_page.wiki_page_references)
68
- # end # commit changes to wiki data store file
69
- #
70
- # ### Some time later... ###
318
+ # end
71
319
  #
72
- # # read wiki data...
73
- # wiki.transaction(true) do # begin read-only transaction, no changes allowed
74
- # wiki.roots.each do |data_root_name|
75
- # p data_root_name
76
- # p wiki[data_root_name]
320
+ # # Read wiki data, setting argument read_only to true.
321
+ # wiki.transaction(true) do
322
+ # wiki.keys.each do |key|
323
+ # puts key
324
+ # puts wiki[key]
77
325
  # end
78
326
  # end
79
327
  #
80
- # == Transaction modes
81
- #
82
- # By default, file integrity is only ensured as long as the operating system
83
- # (and the underlying hardware) doesn't raise any unexpected I/O errors. If an
84
- # I/O error occurs while PStore is writing to its file, then the file will
85
- # become corrupted.
86
- #
87
- # You can prevent this by setting <em>pstore.ultra_safe = true</em>.
88
- # However, this results in a minor performance loss, and only works on platforms
89
- # that support atomic file renames. Please consult the documentation for
90
- # +ultra_safe+ for details.
91
- #
92
- # Needless to say, if you're storing valuable data with PStore, then you should
93
- # backup the PStore files from time to time.
94
328
  class PStore
95
- VERSION = "0.1.1"
329
+ VERSION = "0.1.2"
96
330
 
97
331
  RDWR_ACCESS = {mode: IO::RDWR | IO::CREAT | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
98
332
  RD_ACCESS = {mode: IO::RDONLY | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
@@ -102,21 +336,38 @@ class PStore
102
336
  class Error < StandardError
103
337
  end
104
338
 
105
- # Whether PStore should do its best to prevent file corruptions, even when under
106
- # unlikely-to-occur error conditions such as out-of-space conditions and other
107
- # unusual OS filesystem errors. Setting this flag comes at the price in the form
108
- # of a performance loss.
339
+ # Whether \PStore should do its best to prevent file corruptions,
340
+ # even when an unlikely error (such as memory-error or filesystem error) occurs:
341
+ #
342
+ # - +true+: changes are posted by creating a temporary file,
343
+ # writing the updated data to it, then renaming the file to the given #path.
344
+ # File integrity is maintained.
345
+ # Note: has effect only if the filesystem has atomic file rename
346
+ # (as do POSIX platforms Linux, MacOS, FreeBSD and others).
347
+ #
348
+ # - +false+ (the default): changes are posted by rewinding the open file
349
+ # and writing the updated data.
350
+ # File integrity is maintained if the filesystem raises
351
+ # no unexpected I/O error;
352
+ # if such an error occurs during a write to the store,
353
+ # the file may become corrupted.
109
354
  #
110
- # This flag only has effect on platforms on which file renames are atomic (e.g.
111
- # all POSIX platforms: Linux, MacOS X, FreeBSD, etc). The default value is false.
112
355
  attr_accessor :ultra_safe
113
356
 
357
+ # Returns a new \PStore object.
114
358
  #
115
- # To construct a PStore object, pass in the _file_ path where you would like
116
- # the data to be stored.
359
+ # Argument +file+ is the path to the file in which objects are to be stored;
360
+ # if the file exists, it should be one that was written by \PStore.
117
361
  #
118
- # PStore objects are always reentrant. But if _thread_safe_ is set to true,
119
- # then it will become thread-safe at the cost of a minor performance hit.
362
+ # path = 't.store'
363
+ # store = PStore.new(path)
364
+ #
365
+ # A \PStore object is
366
+ # {reentrant}[https://en.wikipedia.org/wiki/Reentrancy_(computing)].
367
+ # If argument +thread_safe+ is given as +true+,
368
+ # the object is also thread-safe (at the cost of a small performance penalty):
369
+ #
370
+ # store = PStore.new(path, true)
120
371
  #
121
372
  def initialize(file, thread_safe = false)
122
373
  dir = File::dirname(file)
@@ -147,169 +398,160 @@ class PStore
147
398
  end
148
399
  private :in_transaction, :in_transaction_wr
149
400
 
401
+ # Returns the value for the given +key+ if the key exists.
402
+ # +nil+ otherwise;
403
+ # if not +nil+, the returned value is an object or a hierarchy of objects:
404
+ #
405
+ # example_store do |store|
406
+ # store.transaction do
407
+ # store[:foo] # => 0
408
+ # store[:nope] # => nil
409
+ # end
410
+ # end
150
411
  #
151
- # Retrieves a value from the PStore file data, by _name_. The hierarchy of
152
- # Ruby objects stored under that root _name_ will be returned.
412
+ # Returns +nil+ if there is no such key.
153
413
  #
154
- # *WARNING*: This method is only valid in a PStore#transaction. It will
155
- # raise PStore::Error if called at any other time.
414
+ # See also {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
156
415
  #
157
- def [](name)
416
+ # Raises an exception if called outside a transaction block.
417
+ def [](key)
158
418
  in_transaction
159
- @table[name]
419
+ @table[key]
160
420
  end
421
+
422
+ # Like #[], except that it accepts a default value for the store.
423
+ # If the +key+ does not exist:
161
424
  #
162
- # This method is just like PStore#[], save that you may also provide a
163
- # _default_ value for the object. In the event the specified _name_ is not
164
- # found in the data store, your _default_ will be returned instead. If you do
165
- # not specify a default, PStore::Error will be raised if the object is not
166
- # found.
425
+ # - Raises an exception if +default+ is +PStore::Error+.
426
+ # - Returns the value of +default+ otherwise:
167
427
  #
168
- # *WARNING*: This method is only valid in a PStore#transaction. It will
169
- # raise PStore::Error if called at any other time.
428
+ # example_store do |store|
429
+ # store.transaction do
430
+ # store.fetch(:nope, nil) # => nil
431
+ # store.fetch(:nope) # Raises an exception.
432
+ # end
433
+ # end
170
434
  #
171
- def fetch(name, default=PStore::Error)
435
+ # Raises an exception if called outside a transaction block.
436
+ def fetch(key, default=PStore::Error)
172
437
  in_transaction
173
- unless @table.key? name
438
+ unless @table.key? key
174
439
  if default == PStore::Error
175
- raise PStore::Error, format("undefined root name `%s'", name)
440
+ raise PStore::Error, format("undefined key `%s'", key)
176
441
  else
177
442
  return default
178
443
  end
179
444
  end
180
- @table[name]
445
+ @table[key]
181
446
  end
447
+
448
+ # Creates or replaces the value for the given +key+:
182
449
  #
183
- # Stores an individual Ruby object or a hierarchy of Ruby objects in the data
184
- # store file under the root _name_. Assigning to a _name_ already in the data
185
- # store clobbers the old data.
186
- #
187
- # == Example:
188
- #
189
- # require "pstore"
190
- #
191
- # store = PStore.new("data_file.pstore")
192
- # store.transaction do # begin transaction
193
- # # load some data into the store...
194
- # store[:single_object] = "My data..."
195
- # store[:obj_hierarchy] = { "Kev Jackson" => ["rational.rb", "pstore.rb"],
196
- # "James Gray" => ["erb.rb", "pstore.rb"] }
197
- # end # commit changes to data store file
450
+ # example_store do |store|
451
+ # temp.transaction do
452
+ # temp[:bat] = 3
453
+ # end
454
+ # end
198
455
  #
199
- # *WARNING*: This method is only valid in a PStore#transaction and it cannot
200
- # be read-only. It will raise PStore::Error if called at any other time.
456
+ # See also {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
201
457
  #
202
- def []=(name, value)
458
+ # Raises an exception if called outside a transaction block.
459
+ def []=(key, value)
203
460
  in_transaction_wr
204
- @table[name] = value
461
+ @table[key] = value
205
462
  end
463
+
464
+ # Removes and returns the value at +key+ if it exists:
206
465
  #
207
- # Removes an object hierarchy from the data store, by _name_.
466
+ # example_store do |store|
467
+ # store.transaction do
468
+ # store[:bat] = 3
469
+ # store.delete(:bat)
470
+ # end
471
+ # end
208
472
  #
209
- # *WARNING*: This method is only valid in a PStore#transaction and it cannot
210
- # be read-only. It will raise PStore::Error if called at any other time.
473
+ # Returns +nil+ if there is no such key.
211
474
  #
212
- def delete(name)
475
+ # Raises an exception if called outside a transaction block.
476
+ def delete(key)
213
477
  in_transaction_wr
214
- @table.delete name
478
+ @table.delete key
215
479
  end
216
480
 
481
+ # Returns an array of the existing keys:
217
482
  #
218
- # Returns the names of all object hierarchies currently in the store.
483
+ # example_store do |store|
484
+ # store.transaction do
485
+ # store.keys # => [:foo, :bar, :baz]
486
+ # end
487
+ # end
219
488
  #
220
- # *WARNING*: This method is only valid in a PStore#transaction. It will
221
- # raise PStore::Error if called at any other time.
489
+ # Raises an exception if called outside a transaction block.
222
490
  #
223
- def roots
491
+ # PStore#roots is an alias for PStore#keys.
492
+ def keys
224
493
  in_transaction
225
494
  @table.keys
226
495
  end
496
+ alias roots keys
497
+
498
+ # Returns +true+ if +key+ exists, +false+ otherwise:
227
499
  #
228
- # Returns true if the supplied _name_ is currently in the data store.
500
+ # example_store do |store|
501
+ # store.transaction do
502
+ # store.key?(:foo) # => true
503
+ # end
504
+ # end
229
505
  #
230
- # *WARNING*: This method is only valid in a PStore#transaction. It will
231
- # raise PStore::Error if called at any other time.
506
+ # Raises an exception if called outside a transaction block.
232
507
  #
233
- def root?(name)
508
+ # PStore#root? is an alias for PStore#key?.
509
+ def key?(key)
234
510
  in_transaction
235
- @table.key? name
511
+ @table.key? key
236
512
  end
237
- # Returns the path to the data store file.
513
+ alias root? key?
514
+
515
+ # Returns the string file path used to create the store:
516
+ #
517
+ # store.path # => "flat.store"
518
+ #
238
519
  def path
239
520
  @filename
240
521
  end
241
522
 
523
+ # Exits the current transaction block, committing any changes
524
+ # specified in the transaction block.
525
+ # See {Committing or Aborting}[rdoc-ref:PStore@Committing+or+Aborting].
242
526
  #
243
- # Ends the current PStore#transaction, committing any changes to the data
244
- # store immediately.
245
- #
246
- # == Example:
247
- #
248
- # require "pstore"
249
- #
250
- # store = PStore.new("data_file.pstore")
251
- # store.transaction do # begin transaction
252
- # # load some data into the store...
253
- # store[:one] = 1
254
- # store[:two] = 2
255
- #
256
- # store.commit # end transaction here, committing changes
257
- #
258
- # store[:three] = 3 # this change is never reached
259
- # end
260
- #
261
- # *WARNING*: This method is only valid in a PStore#transaction. It will
262
- # raise PStore::Error if called at any other time.
263
- #
527
+ # Raises an exception if called outside a transaction block.
264
528
  def commit
265
529
  in_transaction
266
530
  @abort = false
267
531
  throw :pstore_abort_transaction
268
532
  end
533
+
534
+ # Exits the current transaction block, discarding any changes
535
+ # specified in the transaction block.
536
+ # See {Committing or Aborting}[rdoc-ref:PStore@Committing+or+Aborting].
269
537
  #
270
- # Ends the current PStore#transaction, discarding any changes to the data
271
- # store.
272
- #
273
- # == Example:
274
- #
275
- # require "pstore"
276
- #
277
- # store = PStore.new("data_file.pstore")
278
- # store.transaction do # begin transaction
279
- # store[:one] = 1 # this change is not applied, see below...
280
- # store[:two] = 2 # this change is not applied, see below...
281
- #
282
- # store.abort # end transaction here, discard all changes
283
- #
284
- # store[:three] = 3 # this change is never reached
285
- # end
286
- #
287
- # *WARNING*: This method is only valid in a PStore#transaction. It will
288
- # raise PStore::Error if called at any other time.
289
- #
538
+ # Raises an exception if called outside a transaction block.
290
539
  def abort
291
540
  in_transaction
292
541
  @abort = true
293
542
  throw :pstore_abort_transaction
294
543
  end
295
544
 
545
+ # Opens a transaction block for the store.
546
+ # See {Transactions}[rdoc-ref:PStore@Transactions].
296
547
  #
297
- # Opens a new transaction for the data store. Code executed inside a block
298
- # passed to this method may read and write data to and from the data store
299
- # file.
300
- #
301
- # At the end of the block, changes are committed to the data store
302
- # automatically. You may exit the transaction early with a call to either
303
- # PStore#commit or PStore#abort. See those methods for details about how
304
- # changes are handled. Raising an uncaught Exception in the block is
305
- # equivalent to calling PStore#abort.
306
- #
307
- # If _read_only_ is set to +true+, you will only be allowed to read from the
308
- # data store during the transaction and any attempts to change the data will
309
- # raise a PStore::Error.
548
+ # With argument +read_only+ as +false+, the block may both read from
549
+ # and write to the store.
310
550
  #
311
- # Note that PStore does not support nested transactions.
551
+ # With argument +read_only+ as +true+, the block may not include calls
552
+ # to #transaction, #[]=, or #delete.
312
553
  #
554
+ # Raises an exception if called within a transaction block.
313
555
  def transaction(read_only = false) # :yields: pstore
314
556
  value = nil
315
557
  if !@thread_safe
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pstore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yukihiro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-22 00:00:00.000000000 Z
11
+ date: 2022-12-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Transactional File Storage for Ruby Objects
14
14
  email:
@@ -17,6 +17,7 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
+ - ".github/dependabot.yml"
20
21
  - ".github/workflows/test.yml"
21
22
  - ".gitignore"
22
23
  - Gemfile
@@ -49,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
50
  - !ruby/object:Gem::Version
50
51
  version: '0'
51
52
  requirements: []
52
- rubygems_version: 3.2.2
53
+ rubygems_version: 3.4.0.dev
53
54
  signing_key:
54
55
  specification_version: 4
55
56
  summary: Transactional File Storage for Ruby Objects