D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
alt
/
ruby34
/
share
/
ri
/
system
/
PStore
/
Filename :
cdesc-PStore.ri
back
Copy
U:RDoc::NormalClass[iI"PStore:ET@I"Object;To:RDoc::Markup::Document:@parts[o;;[ho:RDoc::Markup::Paragraph;[I"L\PStore implements a file based persistence mechanism based on a Hash. ;TI">User code can store hierarchies of Ruby objects (values) ;TI")into the data store by name (keys). ;TI"6An object hierarchy may be just a single object. ;TI">User code may later read values back from the data store ;TI"$or even update data, as needed.;To:RDoc::Markup::BlankLine o; ;[I"SThe transactional behavior ensures that any changes succeed or fail together. ;TI"WThis can be used to ensure that the data store is not left in a transitory state, ;TI"8where some values were updated but others were not.;T@o; ;[I"UBehind the scenes, Ruby objects are stored to the data store file with Marshal. ;TI"LThat carries the usual limitations. Proc objects cannot be marshalled, ;TI"for example.;T@o; ;[I"DThere are three important concepts here (details at the links):;T@o:RDoc::Markup::List: @type:BULLET:@items[o:RDoc::Markup::ListItem:@label0;[o; ;[I"K{Store}[rdoc-ref:PStore@The+Store]: a store is an instance of \PStore.;To;;0;[o; ;[I"A{Entries}[rdoc-ref:PStore@Entries]: the store is hash-like; ;TI"/each entry is the key for a stored object.;To;;0;[o; ;[ I"T{Transactions}[rdoc-ref:PStore@Transactions]: each transaction is a collection ;TI"*of prospective changes to the store; ;TI"=a transaction is defined in the block given with a call ;TI"to PStore#transaction.;T@S:RDoc::Markup::Heading: leveli: textI"About the Examples;T@o; ;[I"CExamples on this page need a store that has known properties. ;TI">They can get a new (and populated) store by calling thus:;T@o:RDoc::Markup::Verbatim;[I"example_store do |store| ;TI"- # Example code using store goes here. ;TI" end ;T:@format0o; ;[I"6All we really need to know about +example_store+ ;TI"Iis that it yields a fresh store with a known population of entries; ;TI"its implementation:;T@o;;[I"require 'pstore' ;TI"require 'tempfile' ;TI"3# Yield a pristine store for use in examples. ;TI"def example_store ;TI"/ # Create the store in a temporary file. ;TI"! Tempfile.create do |file| ;TI"" store = PStore.new(file) ;TI" # Populate the store. ;TI" store.transaction do ;TI" store[:foo] = 0 ;TI" store[:bar] = 1 ;TI" store[:baz] = 2 ;TI" end ;TI" yield store ;TI" end ;TI" end ;T;0S;;i;I"The Store;T@o; ;[ I"PThe contents of the store are maintained in a file whose path is specified ;TI"1when the store is created (see PStore.new). ;TI"0The objects are stored and retrieved using ;TI"Tmodule Marshal, which means that certain objects cannot be added to the store; ;TI"0see {Marshal::dump}[rdoc-ref:Marshal.dump].;T@S;;i;I"Entries;T@o; ;[I"-A store may have any number of entries. ;TI"9Each entry has a key and a value, just as in a hash:;T@o;;; ;[o;;0;[o; ;[ I"<Key: as in a hash, the key can be (almost) any object; ;TI"/see {Hash Keys}[rdoc-ref:Hash@Hash+Keys]. ;TI"@You may find it convenient to keep it simple by using only ;TI" symbols or strings as keys.;To;;0;[o; ;[ I"KValue: the value may be any object that can be marshalled by \Marshal ;TI"2(see {Marshal::dump}[rdoc-ref:Marshal.dump]) ;TI"%and in fact may be a collection ;TI"4(e.g., an array, a hash, a set, a range, etc). ;TI"9That collection may in turn contain nested objects, ;TI"*including collections, to any depth; ;TI"/those objects must also be \Marshal-able. ;TI"DSee {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].;T@S;;i;I"Transactions;T@S;;i;I"The Transaction Block;T@o; ;[I"9The block given with a call to method #transaction# ;TI"contains a _transaction_, ;TI"5which consists of calls to \PStore methods that ;TI"%read from or write to the store ;TI"?(that is, all \PStore methods except #transaction itself, ;TI"#path, and Pstore.new):;T@o;;[I"example_store do |store| ;TI" store.transaction do ;TI", store.keys # => [:foo, :bar, :baz] ;TI" store[:bat] = 3 ;TI"2 store.keys # => [:foo, :bar, :baz, :bat] ;TI" end ;TI" end ;T;0o; ;[ I"EExecution of the transaction is deferred until the block exits, ;TI"4and is executed _atomically_ (all-or-nothing): ;TI"=either all transaction calls are executed, or none are. ;TI"/This maintains the integrity of the store.;T@o; ;[I"LOther code in the block (including even calls to #path and PStore.new) ;TI"+is executed immediately, not deferred.;T@o; ;[I"The transaction block:;T@o;;; ;[o;;0;[o; ;[I"3May not contain a nested call to #transaction.;To;;0;[o; ;[I"BIs the only context where methods that read from or write to ;TI"the store are allowed.;T@o; ;[I"DAs seen above, changes in a transaction are made automatically ;TI"when the block exits. ;TI"GThe block may be exited early by calling method #commit or #abort.;T@o;;; ;[o;;0;[o; ;[I"IMethod #commit triggers the update to the store and exits the block:;T@o;;[I"example_store do |store| ;TI" store.transaction do ;TI", store.keys # => [:foo, :bar, :baz] ;TI" store[:bat] = 3 ;TI" store.commit ;TI" fail 'Cannot get here' ;TI" end ;TI" store.transaction do ;TI"! # Update was completed. ;TI"2 store.keys # => [:foo, :bar, :baz, :bat] ;TI" end ;TI" end ;T;0o;;0;[o; ;[I"HMethod #abort discards the update to the store and exits the block:;T@o;;[I"example_store do |store| ;TI" store.transaction do ;TI", store.keys # => [:foo, :bar, :baz] ;TI" store[:bat] = 3 ;TI" store.abort ;TI" fail 'Cannot get here' ;TI" end ;TI" store.transaction do ;TI"% # Update was not completed. ;TI", store.keys # => [:foo, :bar, :baz] ;TI" end ;TI" end ;T;0S;;i;I"Read-Only Transactions;T@o; ;[I"GBy default, a transaction allows both reading from and writing to ;TI"the store:;T@o;;[ I"store.transaction do ;TI"! # Read-write transaction. ;TI"A # Any code except a call to #transaction is allowed here. ;TI" end ;T;0o; ;[I"2If argument +read_only+ is passed as +true+, ;TI"only reading is allowed:;T@o;;[ I" store.transaction(true) do ;TI" # Read-only transaction: ;TI"H # Calls to #transaction, #[]=, and #delete are not allowed here. ;TI" end ;T;0S;;i;I"Hierarchical Values;T@o; ;[I"DThe value for an entry may be a simple object (as seen above). ;TI"?It may also be a hierarchy of objects nested to any depth:;T@o;;[I"+deep_store = PStore.new('deep.store') ;TI"deep_store.transaction do ;TI"& array_of_hashes = [{}, {}, {}] ;TI"6 deep_store[:array_of_hashes] = array_of_hashes ;TI"6 deep_store[:array_of_hashes] # => [{}, {}, {}] ;TI"4 hash_of_arrays = {foo: [], bar: [], baz: []} ;TI"4 deep_store[:hash_of_arrays] = hash_of_arrays ;TI"H deep_store[:hash_of_arrays] # => {:foo=>[], :bar=>[], :baz=>[]} ;TI"4 deep_store[:hash_of_arrays][:foo].push(:bat) ;TI"L deep_store[:hash_of_arrays] # => {:foo=>[:bat], :bar=>[], :baz=>[]} ;TI" end ;T;0o; ;[I"!And recall that you can use ;TI".{dig methods}[rdoc-ref:dig_methods.rdoc] ;TI"(in a returned hierarchy of objects.;T@S;;i;I"Working with the Store;T@S;;i;I"Creating a Store;T@o; ;[I".Use method PStore.new to create a store. ;TI"8The new store creates or opens its containing file:;T@o;;[I"#store = PStore.new('t.store') ;T;0S;;i;I"Modifying the Store;T@o; ;[I"2Use method #[]= to update or create an entry:;T@o;;[I"example_store do |store| ;TI" store.transaction do ;TI"# store[:foo] = 1 # Update. ;TI"# store[:bam] = 1 # Create. ;TI" end ;TI" end ;T;0o; ;[I"+Use method #delete to remove an entry:;T@o;;[I"example_store do |store| ;TI" store.transaction do ;TI" store.delete(:foo) ;TI" store[:foo] # => nil ;TI" end ;TI" end ;T;0S;;i;I"Retrieving Values;T@o; ;[I"CUse method #fetch (allows default) or #[] (defaults to +nil+) ;TI"to retrieve an entry:;T@o;;[I"example_store do |store| ;TI" store.transaction do ;TI"( store[:foo] # => 0 ;TI"* store[:nope] # => nil ;TI"( store.fetch(:baz) # => 2 ;TI"* store.fetch(:nope, nil) # => nil ;TI"5 store.fetch(:nope) # Raises exception. ;TI" end ;TI" end ;T;0S;;i;I"Querying the Store;T@o; ;[I">Use method #key? to determine whether a given key exists:;T@o;;[ I"example_store do |store| ;TI" store.transaction do ;TI"$ store.key?(:foo) # => true ;TI" end ;TI" end ;T;0o; ;[I"'Use method #keys to retrieve keys:;T@o;;[ I"example_store do |store| ;TI" store.transaction do ;TI", store.keys # => [:foo, :bar, :baz] ;TI" end ;TI" end ;T;0o; ;[I"KUse method #path to retrieve the path to the store's underlying file; ;TI"@this method may be called from outside a transaction block:;T@o;;[I"#store = PStore.new('t.store') ;TI"store.path # => "t.store" ;T;0S;;i;I"Transaction Safety;T@o; ;[I"!For transaction safety, see:;T@o;;; ;[o;;0;[o; ;[I":Optional argument +thread_safe+ at method PStore.new.;To;;0;[o; ;[I"Attribute #ultra_safe.;T@o; ;[I"TNeedless to say, if you're storing valuable data with \PStore, then you should ;TI"/backup the \PStore file from time to time.;T@S;;i;I"An Example Store;T@o;;[4I"require "pstore" ;TI" ;TI"# A mock wiki object. ;TI"class WikiPage ;TI" ;TI" attr_reader :page_name ;TI" ;TI"3 def initialize(page_name, author, contents) ;TI" @page_name = page_name ;TI" @revisions = Array.new ;TI"( add_revision(author, contents) ;TI" end ;TI" ;TI"* def add_revision(author, contents) ;TI"+ @revisions << {created: Time.now, ;TI"( author: author, ;TI", contents: contents} ;TI" end ;TI" ;TI" def wiki_page_references ;TI"R [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/) ;TI" end ;TI" ;TI" end ;TI" ;TI"# Create a new wiki page. ;TI"Bhome_page = WikiPage.new("HomePage", "James Edward Gray II", ;TI"J "A page about the JoysOfDocumentation..." ) ;TI" ;TI",wiki = PStore.new("wiki_pages.pstore") ;TI"?# Update page data and the index together, or not at all. ;TI"wiki.transaction do ;TI" # Store page. ;TI"- wiki[home_page.page_name] = home_page ;TI" # Create page index. ;TI"' wiki[:wiki_index] ||= Array.new ;TI" # Update wiki index. ;TI"? wiki[:wiki_index].push(*home_page.wiki_page_references) ;TI" end ;TI" ;TI";# Read wiki data, setting argument read_only to true. ;TI"wiki.transaction(true) do ;TI" wiki.keys.each do |key| ;TI" puts key ;TI" puts wiki[key] ;TI" end ;TI"end;T;0: @fileI"lib/pstore.rb;T:0@omit_headings_from_table_of_contents_below0;0;0[[ I"ultra_safe;TI"RW;T:publicFI"lib/pstore.rb;T[ U:RDoc::Constant[i I"VERSION;TI"PStore::VERSION;T;0o;;[ ;@�;0@�@cRDoc::NormalClass0U;[i I"RDWR_ACCESS;TI"PStore::RDWR_ACCESS;T;0o;;[ ;@�;0@�@@�0U;[i I"RD_ACCESS;TI"PStore::RD_ACCESS;T;0o;;[ ;@�;0@�@@�0U;[i I"WR_ACCESS;TI"PStore::WR_ACCESS;T;0o;;[ ;@�;0@�@@�0U;[i I"CHECKSUM_ALGO;TI"PStore::CHECKSUM_ALGO;T;0o;;[o; ;[I"5Constant for relieving Ruby's garbage collector.;T;@�;0@�@@�0U;[i I"EMPTY_STRING;TI"PStore::EMPTY_STRING;T;0o;;[ ;@�;0@�@@�0U;[i I"EMPTY_MARSHAL_DATA;TI"PStore::EMPTY_MARSHAL_DATA;T;0o;;[ ;@�;0@�@@�0U;[i I"EMPTY_MARSHAL_CHECKSUM;TI"#PStore::EMPTY_MARSHAL_CHECKSUM;T;0o;;[ ;@�;0@�@@�0[ [[I" class;T[[;[[I"new;T@�[:protected[ [:private[ [I" instance;T[[;[[I"[];T@�[I"[]=;T@�[I" abort;T@�[I"commit;T@�[I"delete;T@�[I" fetch;T@�[I" key?;T@�[I" keys;T@�[I" path;T@�[I" root?;T@�[I" roots;T@�[I"transaction;T@�[;[ [;[[I"empty_marshal_checksum;T@�[I"empty_marshal_data;T@�[I"in_transaction;T@�[I"in_transaction_wr;T@�[I"load_data;T@�[I"on_windows?;T@�[I"open_and_lock_file;T@�[I"save_data;T@�[I"/save_data_with_atomic_file_rename_strategy;T@�[I"!save_data_with_fast_strategy;T@�[ [U:RDoc::Context::Section[i 0o;;[ ;0;0[@�@�cRDoc::TopLevel