From 61ebfd3a3496d619b18895b4c1f29c8c5d7c291d Mon Sep 17 00:00:00 2001 From: drbrain Date: Sat, 14 May 2011 00:50:39 +0000 Subject: [PATCH] * lib/yaml/dbm.rb: Add documentation. Patch by Justin Collins. [Ruby 1.9 - Bug #4693] * lib/yaml/store.rb: ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31559 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 +++ lib/yaml/dbm.rb | 117 +++++++++++++++++++++++++++++++++++++++++++--- lib/yaml/store.rb | 43 +++++++++++++++++ 3 files changed, 159 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1d1f8adfaf..5f2859729f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Sat May 14 09:50:10 2011 Eric Hodel + + * lib/yaml/dbm.rb: Add documentation. Patch by Justin Collins. + [Ruby 1.9 - Bug #4693] + * lib/yaml/store.rb: ditto + Sat May 14 09:31:43 2011 Eric Hodel * lib/rdoc.rb: Updated to RDoc 3.6 diff --git a/lib/yaml/dbm.rb b/lib/yaml/dbm.rb index 973e88dbc7..a2fb703239 100644 --- a/lib/yaml/dbm.rb +++ b/lib/yaml/dbm.rb @@ -1,19 +1,48 @@ require 'yaml' require 'dbm' -# -# YAML + DBM = YDBM -# - Same interface as DBM class -# + module YAML +# YAML + DBM = YDBM +# +# YAML::DBM provides the same interface as ::DBM. +# +# However, while DBM only allows strings for both keys and values, +# this library allows one to use most Ruby objects for values +# by first converting them to YAML. Keys must be strings. +# +# Conversion to and from YAML is performed automatically. +# +# See the documentation for ::DBM and ::YAML for more information. class DBM < ::DBM VERSION = "0.1" + + # Return value associated with +key+ from database. + # + # Returns +nil+ if there is no such +key+. def []( key ) fetch( key ) end + + # :call-seq: + # []=( key, value ) + # + # Set +key+ to +value+ in database. + # + # +value+ will be converted to YAML before storage. def []=( key, val ) store( key, val ) end + + # :call-seq: + # fetch( key, ifnone = nil ) + # fetch( key, &block ) + # + # Return value associated with +key+. + # + # If there is no value for +key+ and no block is given, returns +ifnone+. + # + # Otherwise, calls block passing in the given +key+. def fetch( keystr, ifnone = nil ) begin val = super( keystr ) @@ -26,12 +55,20 @@ class DBM < ::DBM ifnone end end + + # Deprecated, used YAML::DBM#key instead. def index( keystr ) super( keystr.to_yaml ) end + + # Returns an array containing the values associated with the given keys. def values_at( *keys ) keys.collect { |k| fetch( k ) } end + + # Deletes value from database assocated with +key+. + # + # Returns value or +nil+. def delete( key ) v = super( key ) if String === v @@ -39,45 +76,89 @@ class DBM < ::DBM end v end - def delete_if + + # Calls the given block once for each +key+, +value+ pair in the database. + # Deletes all entries for which the block returns true. + # + # Returns +self+. + def delete_if # :yields: [key, value] del_keys = keys.dup del_keys.delete_if { |k| yield( k, fetch( k ) ) == false } del_keys.each { |k| delete( k ) } self end + + # Converts the contents of the database to an in-memory Hash, then calls + # Hash#reject with the specified code block, returning a new Hash. def reject hsh = self.to_hash hsh.reject { |k,v| yield k, v } end - def each_pair + + # Calls the given block once for each +key+, +value+ pair in the database. + # + # Returns +self+. + def each_pair # :yields: [key, value] keys.each { |k| yield k, fetch( k ) } self end - def each_value + + # Calls the given block for each value in database. + # + # Returns +self+. + def each_value # :yields: value super { |v| yield YAML.load( v ) } self end + + # Returns an array of values from the database. def values super.collect { |v| YAML.load( v ) } end + + # Returns true if specified value is found in the database. def has_value?( val ) each_value { |v| return true if v == val } return false end + + # Returns a Hash (not a DBM database) created by using each value in the + # database as a key, with the corresponding key as its value. + # + # Note that all values in the hash will be Strings, but the keys will be + # actual objects. def invert h = {} keys.each { |k| h[ self.fetch( k ) ] = k } h end + + # Replaces the contents of the database with the contents of the specified + # object. Takes any object which implements the each_pair method, including + # Hash and DBM objects. def replace( hsh ) clear update( hsh ) end + + # Removes a [key, value] pair from the database, and returns it. + # If the database is empty, returns +nil+. + # + # The order in which values are removed/returned is not guaranteed. def shift a = super a[1] = YAML.load( a[1] ) if a a end + + # :call-seq: + # select( &block ) + # select( *keys ) + # + # If a block is provided, returns a new array containing [key, value] pairs + # for which the block returns true. + # + # Otherwise, same as #values_at def select( *keys ) if block_given? self.keys.collect { |k| v = self[k]; [k, v] if yield k, v }.compact @@ -85,26 +166,48 @@ class DBM < ::DBM values_at( *keys ) end end + + # :call-seq: + # store( key, value ) + # + #Stores +value+ in database with +key+ as the index. +value+ is converted + #to YAML before being stored. + # + #Returns +value+ def store( key, val ) super( key, val.to_yaml ) val end + + # Updates the database with multiple values from the specified object. + # Takes any object which implements the each_pair method, including + # Hash and DBM objects. + # + # Returns +self+. def update( hsh ) hsh.keys.each do |k| self.store( k, hsh.fetch( k ) ) end self end + + # Converts the contents of the database to an array of [key, value] arrays, + # and returns it. def to_a a = [] keys.each { |k| a.push [ k, self.fetch( k ) ] } a end + + + # Converts the contents of the database to an in-memory Hash object, and + # returns it. def to_hash h = {} keys.each { |k| h[ k ] = self.fetch( k ) } h end + alias :each :each_pair end diff --git a/lib/yaml/store.rb b/lib/yaml/store.rb index a7f8a5657d..82d6ee1aaa 100644 --- a/lib/yaml/store.rb +++ b/lib/yaml/store.rb @@ -4,7 +4,48 @@ require 'yaml' require 'pstore' +# YAML::Store provides the same functionality as PStore, except it uses YAML +# to dump objects instead of Marshal. +# +# == Example +# +# require 'yaml/store' +# +# Person = Struct.new :first_name, :last_name +# +# people = [Person.new("Bob", "Smith"), Person.new("Mary", "Johnson")] +# +# store = YAML::Store.new "test.store" +# +# store.transaction do +# store["people"] = people +# store["greeting"] = { "hello" => "world" } +# end +# +# After running the above code, the contents of "test.store" will be: +# +# --- +# people: +# - !ruby/struct:Person +# first_name: Bob +# last_name: Smith +# - !ruby/struct:Person +# first_name: Mary +# last_name: Johnson +# greeting: +# hello: world + class YAML::Store < PStore + + # :call-seq: + # initialize( file_name, yaml_opts = {} ) + # + # Creates a new YAML::Store object, which will store data in +file_name+. + # If the file does not already exist, it will be created. + # + # + # Options passed in through +yaml_opts+ will be used when converting the + # store to YAML via Hash#to_yaml(). def initialize( *o ) @opt = {} if String === o.first @@ -15,6 +56,8 @@ class YAML::Store < PStore end end + # :stopdoc: + def dump(table) @table.to_yaml(@opt) end