mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[ruby/pstore] Enhanced RDoc
https://github.com/ruby/pstore/commit/81a266d88c
This commit is contained in:
parent
7b78aba53a
commit
8715ecd04b
1 changed files with 345 additions and 156 deletions
501
lib/pstore.rb
501
lib/pstore.rb
|
@ -10,87 +10,268 @@
|
|||
|
||||
require "digest"
|
||||
|
||||
# An instance of class \PStore can store and retrieve Ruby objects --
|
||||
# not just strings or raw data, but objects of many kinds.
|
||||
# There are three key terms here (details at the links):
|
||||
#
|
||||
# PStore implements a file based persistence mechanism based on a Hash. User
|
||||
# code can store hierarchies of Ruby objects (values) into the data store file
|
||||
# by name (keys). An object hierarchy may be just a single object. User code
|
||||
# may later read values back from the data store or even update data, as needed.
|
||||
# - {Store}[rdoc-ref:PStore@The+Store]: a store is an instance of \PStore.
|
||||
# - {Roots}[rdoc-ref:PStore@Roots]: the store is hash-like;
|
||||
# each root is a key for a stored object.
|
||||
# - {Transactions}[rdoc-ref:PStore@Transactions]: each transaction is a ollection
|
||||
# of prospective changes to the store;
|
||||
# a transaction is defined in the block given with a call
|
||||
# to PStore#transaction.
|
||||
#
|
||||
# The transactional behavior ensures that any changes succeed or fail together.
|
||||
# This can be used to ensure that the data store is not left in a transitory
|
||||
# state, where some values were updated but others were not.
|
||||
# == About the Examples
|
||||
#
|
||||
# Behind the scenes, Ruby objects are stored to the data store file with
|
||||
# Marshal. That carries the usual limitations. Proc objects cannot be
|
||||
# marshalled, for example.
|
||||
# All examples on this page assume that the following code has been executed:
|
||||
#
|
||||
# == Usage example:
|
||||
# require 'pstore'
|
||||
# # Create a store with file +flat.store+.
|
||||
# store = PStore.new('flat.store')
|
||||
# # Store some objects.
|
||||
# store.transaction do
|
||||
# store[:foo] = 0
|
||||
# store[:bar] = 1
|
||||
# store[:baz] = 2
|
||||
# end
|
||||
#
|
||||
# To avoid modifying the example store, some examples first execute
|
||||
# <tt>temp = store.dup</tt>, then apply changes to +temp+
|
||||
#
|
||||
# == The Store
|
||||
#
|
||||
# The contents of the store are maintained in a file whose path is specified
|
||||
# when the store is created (see PStore.new):
|
||||
#
|
||||
# - Ruby objects put into the store are serialized as string data
|
||||
# and written to the file;
|
||||
# - Data retrieved from the store is read from the file and deserialized
|
||||
# to form Ruby objects.
|
||||
#
|
||||
# The objects are serialized and deserialized using
|
||||
# module Marshal, which means that certain objects cannot be added to the store;
|
||||
# see {Marshal::dump}[https://docs.ruby-lang.org/en/master/Marshal.html#method-c-dump].
|
||||
#
|
||||
# == Roots
|
||||
#
|
||||
# A store may have any number of entries, called _roots_.
|
||||
# Each root has a key and a value, just as in a hash:
|
||||
#
|
||||
# - Key: as in a hash, the key can be (almost) any object;
|
||||
# see {Hash}[https://docs.ruby-lang.org/en/master/Hash.html].
|
||||
# You may find it convenient to keep it simple by using only
|
||||
# symbols or strings as keys.
|
||||
# - Value: the value truly may be any object, and in fact can be a collection
|
||||
# (e.g., an array, a hash, a set, a range, etc).
|
||||
# That collection may in turn contain nested collections, to any depth.
|
||||
# See {Deep Root Values}[rdoc-ref:PStore@Deep+Root+Values].
|
||||
#
|
||||
# == Transactions
|
||||
#
|
||||
# A call to PStore#transaction must have a block.
|
||||
#
|
||||
# A transaction consists of just those \PStore method calls in the block
|
||||
# that would modify the store; those methods are #[]= and #delete.
|
||||
# Note that the block may contain any code whatsoever
|
||||
# except a nested call to #transaction.
|
||||
#
|
||||
# An instance method in \PStore may be called only from within a transaction
|
||||
# (with the exception the #path may be called from anywhere).
|
||||
# This assures that the call is executed only when the store is secure and stable.
|
||||
#
|
||||
# When the transaction block exits,
|
||||
# the specified changes are made automatically.
|
||||
# (and atomically; that is, either all changes are posted, or none are).
|
||||
#
|
||||
# Exactly how the changes are posted
|
||||
# depends on the value of attribute #ultra_safe (details at the link).
|
||||
#
|
||||
# The block may be exited early by calling method #commit or #abort.
|
||||
#
|
||||
# - Method #commit triggers the update to the store and exits the block:
|
||||
#
|
||||
# temp = store.dup
|
||||
# temp.transaction do
|
||||
# temp.roots # => [:foo, :bar, :baz]
|
||||
# temp[:bat] = 3
|
||||
# temp.commit
|
||||
# fail 'Cannot get here'
|
||||
# end
|
||||
# temp.transaction do
|
||||
# # Update was completed.
|
||||
# store.roots # => [:foo, :bar, :baz, :bat]
|
||||
# end
|
||||
#
|
||||
# - Method #abort discards the update to the store and exits the block:
|
||||
#
|
||||
# store.transaction do
|
||||
# store[:bam] = 4
|
||||
# store.abort
|
||||
# fail 'Cannot get here'
|
||||
# end
|
||||
# store.transaction do
|
||||
# # Update was not completed.
|
||||
# store[:bam] # => nil
|
||||
# end
|
||||
#
|
||||
# Each transaction is either:
|
||||
#
|
||||
# - Read-write (the default):
|
||||
#
|
||||
# store.transaction do
|
||||
# # Read-write transaction.
|
||||
# # Any code except a call to #transaction is allowed here.
|
||||
# end
|
||||
#
|
||||
# - Read-only (optional argument +read_only+ set to +true+):
|
||||
#
|
||||
# store.transaction(true) do
|
||||
# # Read-only transaction:
|
||||
# # Calls to #transaction, #[]=, and #delete are not allowed here.
|
||||
# end
|
||||
#
|
||||
# == Deep Root Values
|
||||
#
|
||||
# The value for a root may be a simple object (as seen above).
|
||||
# It may also be a hierarchy of objects nested to any depth:
|
||||
#
|
||||
# deep_store = PStore.new('deep.store')
|
||||
# deep_store.transaction do
|
||||
# array_of_hashes = [{}, {}, {}]
|
||||
# deep_store[:array_of_hashes] = array_of_hashes
|
||||
# deep_store[:array_of_hashes] # => [{}, {}, {}]
|
||||
# hash_of_arrays = {foo: [], bar: [], baz: []}
|
||||
# deep_store[:hash_of_arrays] = hash_of_arrays
|
||||
# deep_store[:hash_of_arrays] # => {:foo=>[], :bar=>[], :baz=>[]}
|
||||
# deep_store[:hash_of_arrays][:foo].push(:bat)
|
||||
# deep_store[:hash_of_arrays] # => {:foo=>[:bat], :bar=>[], :baz=>[]}
|
||||
# end
|
||||
#
|
||||
# And recall that you can use
|
||||
# {dig methods}[https://docs.ruby-lang.org/en/master/dig_methods_rdoc.html]
|
||||
# in a returned hierarchy of objects.
|
||||
#
|
||||
# == Working with the Store
|
||||
#
|
||||
# === Creating a Store
|
||||
#
|
||||
# Use method PStore.new to create a store.
|
||||
# The new store creates or opens its containing file:
|
||||
#
|
||||
# store = PStore.new('t.store')
|
||||
#
|
||||
# === Modifying the Store
|
||||
#
|
||||
# Use method #[]= to update or create a root:
|
||||
#
|
||||
# temp = store.dup
|
||||
# temp.transaction do
|
||||
# temp[:foo] = 1 # Update.
|
||||
# temp[:bam] = 1 # Create.
|
||||
# end
|
||||
#
|
||||
# Use method #delete to remove a root:
|
||||
#
|
||||
# temp = store.dup
|
||||
# temp.transaction do
|
||||
# temp.delete(:foo)
|
||||
# temp[:foo] # => nil
|
||||
# end
|
||||
#
|
||||
# === Retrieving Stored Objects
|
||||
#
|
||||
# Use method #fetch (allows default) or #[] (defaults to +nil+)
|
||||
# to retrieve a root:
|
||||
#
|
||||
# store.transaction do
|
||||
# store[:foo] # => 0
|
||||
# store[:nope] # => nil
|
||||
# store.fetch(:baz) # => 2
|
||||
# store.fetch(:nope, nil) # => nil
|
||||
# store.fetch(:nope) # Raises exception.
|
||||
# end
|
||||
#
|
||||
# === Querying the Store
|
||||
#
|
||||
# Use method #root? to determine whether a given root exists:
|
||||
#
|
||||
# store.transaction do
|
||||
# store.root?(:foo) # => true.
|
||||
# end
|
||||
#
|
||||
# Use method #roots to retrieve root keys:
|
||||
#
|
||||
# store.transaction do
|
||||
# store.roots # => [:foo, :bar, :baz].
|
||||
# end
|
||||
#
|
||||
# Use method #path to retrieve the path to the store's underlying file:
|
||||
#
|
||||
# store.transaction do
|
||||
# store.path # => "flat.store"
|
||||
# end
|
||||
#
|
||||
# == Transaction Safety
|
||||
#
|
||||
# For transaction safety, see:
|
||||
#
|
||||
# - Optional argument +thread_safe+ at method PStore.new.
|
||||
# - Attribute #ultra_safe.
|
||||
#
|
||||
# Needless to say, if you're storing valuable data with \PStore, then you should
|
||||
# backup the \PStore file from time to time.
|
||||
#
|
||||
# == An Example Store
|
||||
#
|
||||
# require "pstore"
|
||||
#
|
||||
# # a mock wiki object...
|
||||
# # A mock wiki object.
|
||||
# class WikiPage
|
||||
# def initialize( page_name, author, contents )
|
||||
# @page_name = page_name
|
||||
# @revisions = Array.new
|
||||
#
|
||||
# add_revision(author, contents)
|
||||
# end
|
||||
#
|
||||
# attr_reader :page_name
|
||||
#
|
||||
# def add_revision( author, contents )
|
||||
# @revisions << { :created => Time.now,
|
||||
# :author => author,
|
||||
# :contents => contents }
|
||||
# def initialize(page_name, author, contents)
|
||||
# @page_name = page_name
|
||||
# @revisions = Array.new
|
||||
# add_revision(author, contents)
|
||||
# end
|
||||
#
|
||||
# def add_revision(author, contents)
|
||||
# @revisions << {created: Time.now,
|
||||
# author: author,
|
||||
# contents: contents}
|
||||
# end
|
||||
#
|
||||
# def wiki_page_references
|
||||
# [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/)
|
||||
# end
|
||||
#
|
||||
# # ...
|
||||
# end
|
||||
#
|
||||
# # create a new page...
|
||||
# home_page = WikiPage.new( "HomePage", "James Edward Gray II",
|
||||
# "A page about the JoysOfDocumentation..." )
|
||||
# # Create a new wiki page.
|
||||
# home_page = WikiPage.new("HomePage", "James Edward Gray II",
|
||||
# "A page about the JoysOfDocumentation..." )
|
||||
#
|
||||
# # then we want to update page data and the index together, or not at all...
|
||||
# wiki = PStore.new("wiki_pages.pstore")
|
||||
# wiki.transaction do # begin transaction; do all of this or none of it
|
||||
# # store page...
|
||||
# # Update page data and the index together, or not at all.
|
||||
# wiki.transaction do
|
||||
# # Store page.
|
||||
# wiki[home_page.page_name] = home_page
|
||||
# # ensure that an index has been created...
|
||||
# # Create page index.
|
||||
# wiki[:wiki_index] ||= Array.new
|
||||
# # update wiki index...
|
||||
# # Update wiki index.
|
||||
# wiki[:wiki_index].push(*home_page.wiki_page_references)
|
||||
# end # commit changes to wiki data store file
|
||||
# end
|
||||
#
|
||||
# ### Some time later... ###
|
||||
#
|
||||
# # read wiki data...
|
||||
# wiki.transaction(true) do # begin read-only transaction, no changes allowed
|
||||
# wiki.roots.each do |data_root_name|
|
||||
# p data_root_name
|
||||
# p wiki[data_root_name]
|
||||
# # Read wiki data, setting argument read_only to true.
|
||||
# wiki.transaction(true) do
|
||||
# wiki.roots.each do |root|
|
||||
# puts root
|
||||
# puts wiki[root]
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# == Transaction modes
|
||||
#
|
||||
# By default, file integrity is only ensured as long as the operating system
|
||||
# (and the underlying hardware) doesn't raise any unexpected I/O errors. If an
|
||||
# I/O error occurs while PStore is writing to its file, then the file will
|
||||
# become corrupted.
|
||||
#
|
||||
# You can prevent this by setting <em>pstore.ultra_safe = true</em>.
|
||||
# However, this results in a minor performance loss, and only works on platforms
|
||||
# that support atomic file renames. Please consult the documentation for
|
||||
# +ultra_safe+ for details.
|
||||
#
|
||||
# Needless to say, if you're storing valuable data with PStore, then you should
|
||||
# backup the PStore files from time to time.
|
||||
class PStore
|
||||
VERSION = "0.1.1"
|
||||
|
||||
|
@ -102,21 +283,38 @@ class PStore
|
|||
class Error < StandardError
|
||||
end
|
||||
|
||||
# Whether PStore should do its best to prevent file corruptions, even when under
|
||||
# unlikely-to-occur error conditions such as out-of-space conditions and other
|
||||
# unusual OS filesystem errors. Setting this flag comes at the price in the form
|
||||
# of a performance loss.
|
||||
# Whether \PStore should do its best to prevent file corruptions,
|
||||
# even when an unlikely error (such as memory-error or filesystem error) occurs:
|
||||
#
|
||||
# - +true+: changes are posted by creating a temporary file,
|
||||
# writing the updated data to it, then renaming the file to the given #path.
|
||||
# File integrity is maintained.
|
||||
# Note: has effect only if the filesystem has atomic file rename
|
||||
# (as do POSIX platforms Linux, MacOS, FreeBSD and others).
|
||||
#
|
||||
# - +false+ (the default): changes are posted by rewinding the open file
|
||||
# and writing the updated data.
|
||||
# File integrity is maintained if the filesystem raises
|
||||
# no unexpected I/O error;
|
||||
# if such an error occurs during a write to the store,
|
||||
# the file may become corrupted.
|
||||
#
|
||||
# This flag only has effect on platforms on which file renames are atomic (e.g.
|
||||
# all POSIX platforms: Linux, MacOS X, FreeBSD, etc). The default value is false.
|
||||
attr_accessor :ultra_safe
|
||||
|
||||
# Returns a new \PStore object.
|
||||
#
|
||||
# To construct a PStore object, pass in the _file_ path where you would like
|
||||
# the data to be stored.
|
||||
# Argument +file+ is the path to the file in which objects are to be stored;
|
||||
# if the file exists, it must be in a Marshal-compatible format:
|
||||
#
|
||||
# PStore objects are always reentrant. But if _thread_safe_ is set to true,
|
||||
# then it will become thread-safe at the cost of a minor performance hit.
|
||||
# path = 't.store'
|
||||
# store = PStore.new(path)
|
||||
#
|
||||
# A \PStore object is
|
||||
# {reentrant}[https://en.wikipedia.org/wiki/Reentrancy_(computing)];
|
||||
# if argument +thread_safe+ is given as +true+,
|
||||
# the object is also thread-safe (at the cost of a small performance penalty):
|
||||
#
|
||||
# store = PStore.new(path, true)
|
||||
#
|
||||
def initialize(file, thread_safe = false)
|
||||
dir = File::dirname(file)
|
||||
|
@ -147,27 +345,43 @@ class PStore
|
|||
end
|
||||
private :in_transaction, :in_transaction_wr
|
||||
|
||||
# :call-seq:
|
||||
# pstore[key]
|
||||
#
|
||||
# Retrieves a value from the PStore file data, by _name_. The hierarchy of
|
||||
# Ruby objects stored under that root _name_ will be returned.
|
||||
# Returns the deserialized value of the root for the given +key+ if it exists.
|
||||
# +nil+ otherwise;
|
||||
# if not +nil+, the returned value is an object or a hierarchy of objects:
|
||||
#
|
||||
# *WARNING*: This method is only valid in a PStore#transaction. It will
|
||||
# raise PStore::Error if called at any other time.
|
||||
# store.transaction do
|
||||
# store[:foo] # => 0
|
||||
# store[:nope] # => nil
|
||||
# end
|
||||
#
|
||||
# Returns +nil+ if there is no such root.
|
||||
#
|
||||
# See also {Deep Root Values}[rdoc-ref:PStore@Deep+Root+Values].
|
||||
#
|
||||
# Raises an exception if called outside a transaction block.
|
||||
def [](name)
|
||||
in_transaction
|
||||
@table[name]
|
||||
end
|
||||
|
||||
# :call-seq:
|
||||
# fetch(key)
|
||||
#
|
||||
# This method is just like PStore#[], save that you may also provide a
|
||||
# _default_ value for the object. In the event the specified _name_ is not
|
||||
# found in the data store, your _default_ will be returned instead. If you do
|
||||
# not specify a default, PStore::Error will be raised if the object is not
|
||||
# found.
|
||||
# Like #[], except that it accepts a default value for the store.
|
||||
# If the root for the given +key+ does not exist:
|
||||
#
|
||||
# *WARNING*: This method is only valid in a PStore#transaction. It will
|
||||
# raise PStore::Error if called at any other time.
|
||||
# - Raises an exception if +default+ is +PStore::Error+.
|
||||
# - Returns the value of +default+ otherwise:
|
||||
#
|
||||
# store.transaction do
|
||||
# store.fetch(:nope, nil) # => nil
|
||||
# store.fetch(:nope) # Raises an exception.
|
||||
# end
|
||||
#
|
||||
# Raises an exception if called outside a transaction block.
|
||||
def fetch(name, default=PStore::Error)
|
||||
in_transaction
|
||||
unless @table.key? name
|
||||
|
@ -179,137 +393,112 @@ class PStore
|
|||
end
|
||||
@table[name]
|
||||
end
|
||||
|
||||
# :call-seq:
|
||||
# pstore[key] = value
|
||||
#
|
||||
# Stores an individual Ruby object or a hierarchy of Ruby objects in the data
|
||||
# store file under the root _name_. Assigning to a _name_ already in the data
|
||||
# store clobbers the old data.
|
||||
# Creates or replaces an object or hierarchy of objects
|
||||
# at the root for +key+:
|
||||
#
|
||||
# == Example:
|
||||
# store = PStore.new('t.store')
|
||||
# store.transaction do
|
||||
# store[:bat] = 3
|
||||
# end
|
||||
#
|
||||
# require "pstore"
|
||||
#
|
||||
# store = PStore.new("data_file.pstore")
|
||||
# store.transaction do # begin transaction
|
||||
# # load some data into the store...
|
||||
# store[:single_object] = "My data..."
|
||||
# store[:obj_hierarchy] = { "Kev Jackson" => ["rational.rb", "pstore.rb"],
|
||||
# "James Gray" => ["erb.rb", "pstore.rb"] }
|
||||
# end # commit changes to data store file
|
||||
#
|
||||
# *WARNING*: This method is only valid in a PStore#transaction and it cannot
|
||||
# be read-only. It will raise PStore::Error if called at any other time.
|
||||
# See also {Deep Root Values}[rdoc-ref:PStore@Deep+Root+Values].
|
||||
#
|
||||
# Raises an exception if called outside a transaction block.
|
||||
def []=(name, value)
|
||||
in_transaction_wr
|
||||
@table[name] = value
|
||||
end
|
||||
|
||||
# :call-seq:
|
||||
# delete(key)
|
||||
#
|
||||
# Removes an object hierarchy from the data store, by _name_.
|
||||
# Removes and returns the root for +key+ if it exists:
|
||||
#
|
||||
# *WARNING*: This method is only valid in a PStore#transaction and it cannot
|
||||
# be read-only. It will raise PStore::Error if called at any other time.
|
||||
# store = PStore.new('t.store')
|
||||
# store.transaction do
|
||||
# store[:bat] = 3
|
||||
# store.delete(:bat)
|
||||
# end
|
||||
#
|
||||
# Returns +nil+ if there is no such root.
|
||||
#
|
||||
# Raises an exception if called outside a transaction block.
|
||||
def delete(name)
|
||||
in_transaction_wr
|
||||
@table.delete name
|
||||
end
|
||||
|
||||
# Returns an array of the keys of the existing roots:
|
||||
#
|
||||
# Returns the names of all object hierarchies currently in the store.
|
||||
#
|
||||
# *WARNING*: This method is only valid in a PStore#transaction. It will
|
||||
# raise PStore::Error if called at any other time.
|
||||
# store.transaction do
|
||||
# store.roots # => [:foo, :bar, :baz]
|
||||
# end
|
||||
#
|
||||
# Raises an exception if called outside a transaction block.
|
||||
def roots
|
||||
in_transaction
|
||||
@table.keys
|
||||
end
|
||||
|
||||
# :call-seq:
|
||||
# root?(key)
|
||||
#
|
||||
# Returns true if the supplied _name_ is currently in the data store.
|
||||
# Returns +true+ if there is a root for +key+, +false+ otherwise:
|
||||
#
|
||||
# *WARNING*: This method is only valid in a PStore#transaction. It will
|
||||
# raise PStore::Error if called at any other time.
|
||||
# store.transaction do
|
||||
# store.root?(:foo) # => true
|
||||
# end
|
||||
#
|
||||
# Raises an exception if called outside a transaction block.
|
||||
def root?(name)
|
||||
in_transaction
|
||||
@table.key? name
|
||||
end
|
||||
# Returns the path to the data store file.
|
||||
|
||||
# Returns the string file path used to create the store:
|
||||
#
|
||||
# store.path # => "flat.store"
|
||||
#
|
||||
def path
|
||||
@filename
|
||||
end
|
||||
|
||||
# Exits the current transaction block after committing any changes
|
||||
# specified in that block.
|
||||
# See {Committing or Aborting}[rdoc-ref:PStore@Committing+or+Aborting].
|
||||
#
|
||||
# Ends the current PStore#transaction, committing any changes to the data
|
||||
# store immediately.
|
||||
#
|
||||
# == Example:
|
||||
#
|
||||
# require "pstore"
|
||||
#
|
||||
# store = PStore.new("data_file.pstore")
|
||||
# store.transaction do # begin transaction
|
||||
# # load some data into the store...
|
||||
# store[:one] = 1
|
||||
# store[:two] = 2
|
||||
#
|
||||
# store.commit # end transaction here, committing changes
|
||||
#
|
||||
# store[:three] = 3 # this change is never reached
|
||||
# end
|
||||
#
|
||||
# *WARNING*: This method is only valid in a PStore#transaction. It will
|
||||
# raise PStore::Error if called at any other time.
|
||||
#
|
||||
# Raises an exception if called outside a transaction block.
|
||||
def commit
|
||||
in_transaction
|
||||
@abort = false
|
||||
throw :pstore_abort_transaction
|
||||
end
|
||||
|
||||
# Exits the current transaction block, ignoring any changes
|
||||
# specified in that block.
|
||||
# See {Committing or Aborting}[rdoc-ref:PStore@Committing+or+Aborting].
|
||||
#
|
||||
# Ends the current PStore#transaction, discarding any changes to the data
|
||||
# store.
|
||||
#
|
||||
# == Example:
|
||||
#
|
||||
# require "pstore"
|
||||
#
|
||||
# store = PStore.new("data_file.pstore")
|
||||
# store.transaction do # begin transaction
|
||||
# store[:one] = 1 # this change is not applied, see below...
|
||||
# store[:two] = 2 # this change is not applied, see below...
|
||||
#
|
||||
# store.abort # end transaction here, discard all changes
|
||||
#
|
||||
# store[:three] = 3 # this change is never reached
|
||||
# end
|
||||
#
|
||||
# *WARNING*: This method is only valid in a PStore#transaction. It will
|
||||
# raise PStore::Error if called at any other time.
|
||||
#
|
||||
# Raises an exception if called outside a transaction block.
|
||||
def abort
|
||||
in_transaction
|
||||
@abort = true
|
||||
throw :pstore_abort_transaction
|
||||
end
|
||||
|
||||
# Defines a transaction block for the store.
|
||||
# See {Transactions}[rdoc-ref:PStore@Transactions].
|
||||
#
|
||||
# Opens a new transaction for the data store. Code executed inside a block
|
||||
# passed to this method may read and write data to and from the data store
|
||||
# file.
|
||||
# With argument +read_only+ as +false+, the block may contain any Ruby code,
|
||||
# including calls to \PStore methods other #transaction.
|
||||
#
|
||||
# At the end of the block, changes are committed to the data store
|
||||
# automatically. You may exit the transaction early with a call to either
|
||||
# PStore#commit or PStore#abort. See those methods for details about how
|
||||
# changes are handled. Raising an uncaught Exception in the block is
|
||||
# equivalent to calling PStore#abort.
|
||||
#
|
||||
# If _read_only_ is set to +true+, you will only be allowed to read from the
|
||||
# data store during the transaction and any attempts to change the data will
|
||||
# raise a PStore::Error.
|
||||
#
|
||||
# Note that PStore does not support nested transactions.
|
||||
# With argument +read_only+ as +true+, the block may not include calls
|
||||
# to #transaction, #[]=, or #delete.
|
||||
#
|
||||
# Raises an exception if called within a transaction block.
|
||||
def transaction(read_only = false) # :yields: pstore
|
||||
value = nil
|
||||
if !@thread_safe
|
||||
|
|
Loading…
Add table
Reference in a new issue