Skip to content

Commit

Permalink
Add #hash and #dup methods and YARd-out the docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
trans committed May 21, 2012
1 parent 841d30c commit 4085c51
Showing 1 changed file with 90 additions and 6 deletions.
96 changes: 90 additions & 6 deletions lib/ostruct2.rb
@@ -1,5 +1,16 @@
# A better OpenStruct class. # A better OpenStruct class.
# #
# This OpenStruct class allows almost any member name to be used.
# The only exceptions are methods starting with double underscores,
# e.g. `__id__`, and a few neccessary public methods: `hash`, `dup`,
# `to_enum`, `to_h` and `inspect`.
#
# To offset the loss of most methods, OpenStruct provides numerous
# bang-methods which can be used to manipulate the data, e.g. `#each!`.
#
# This improved version of OpenStruct also has no issues with being
# cloned or marshalled since it does not depend on singleton methods.
#
class OpenStruct < BasicObject class OpenStruct < BasicObject


class << self class << self
Expand All @@ -18,12 +29,18 @@ def cascade(data=nil)
alias :auto :cascade alias :auto :cascade
end end


#
# Initialize new instance of OpenStruct.
#
# @param [Hash] data
# #
def initialize(data=nil, &block) def initialize(data=nil, &block)
@table = ::Hash.new(&block) @table = ::Hash.new(&block)
update!(data || {}) update!(data || {})
end end


#
# Dispatch unrecognized member calls.
# #
def method_missing(sym, *args, &blk) def method_missing(sym, *args, &blk)
str = sym.to_s str = sym.to_s
Expand All @@ -42,27 +59,37 @@ def method_missing(sym, *args, &blk)
end end
end end


#
# CRUD method for listing all keys. # CRUD method for listing all keys.
#
def keys! def keys!
@table.keys @table.keys
end end


#
# Also a CRUD method like #read!, but for checking for the existence of a key. # Also a CRUD method like #read!, but for checking for the existence of a key.
#
def key?(key) def key?(key)
@table.key?(key.to_sym) @table.key?(key.to_sym)
end end


#
# The CRUD method for read. # The CRUD method for read.
#
def read!(key) def read!(key)
@table[key.to_sym] @table[key.to_sym]
end end


#
# The CRUD method for create and update. # The CRUD method for create and update.
#
def store!(key, value) def store!(key, value)
@table[key.to_sym] = value @table[key.to_sym] = value
end end


#
# The CRUD method for destroy. # The CRUD method for destroy.
#
def delete!(key) def delete!(key)
@table.delete(key.to_sym) @table.delete(key.to_sym)
end end
Expand All @@ -75,37 +102,78 @@ def fetch!(key)
read!(key) read!(key)
end end


#
# If key is not present raise a KeyError.
#
# @param [#to_sym] key
#
# @raise [KeyError] If key is not present.
#
# @return key
#
def key!(key)
return key if key?(key)
::Kernel.raise ::KeyError, ("key not found: %s" % [key.inspect])
end

#
# Alias for `#read!`.
#
# @param [#to_sym] key
#
# @return [Object]
# #
def [](key) def [](key)
read!(key) read!(key)
end end


#
# Alias for `#store!`.
#
# @param [#to_sym] key
#
# @param [Object] value
#
# @return value.
# #
def []=(key, value) def []=(key, value)
store!(key, value) store!(key, value)
end end


#
# CRUDified each. # CRUDified each.
#
# @return nothing
#
def each! def each!
@table.each_key do |key| @table.each_key do |key|
yield(key, read!(key)) yield(key, read!(key))
end end
end end


#
# CRUDified update method. # CRUDified update method.
#
# @return [self]
#
def update!(other) def update!(other)
other.each do |k,v| other.each do |k,v|
store!(k,v) store!(k,v)
end end
self
end end


#
# Merge this OpenStruct with another OpenStruct or Hash object
# returning a new OpenStruct instance.
# #
# IMPORTANT! This method does not act in-place like `Hash#merge!`, # IMPORTANT! This method does not act in-place like `Hash#merge!`,
# rather it works like `Hash#merge`. # rather it works like `Hash#merge`.
# #
# @return [OpenStruct]
#
def merge!(other) def merge!(other)
# TODO: is there anyway to #dup a BasicObject subclass instance? o = dup
o = ::OpenStruct.new(@table, &@table.default_proc)
other.each do |k,v| other.each do |k,v|
o.store!(k,v) o.store!(k,v)
end end
Expand All @@ -122,25 +190,41 @@ def empty?
# #
# Get a duplicate of the underlying table. # Get a duplicate of the underlying table.
# #
# @return [Hash]
#
def to_h def to_h
@table.dup @table.dup
end end


#
# Create an enumerator based on `#each!`.
#
# @return [Enumerator]
# #
def to_enum def to_enum
::Enumerator.new(self, :each!) ::Enumerator.new(self, :each!)
end end


# #
# If key is not present raise a KeyError. # Duplicate OpenStruct object.
# #
def key!(key) # @return [OpenStruct] Duplicate instance.
return key if key?(key) #
::Kernel.raise ::KeyError, ("key not found: %s" % [key.inspect]) def dup
::OpenStruct.new(@table, &@table.default_proc)
end

#
# Hash number.
#
def hash
@table.hash
end end


# #
# Inspect OpenStruct object.
# #
# @return [String]
# #
def inspect def inspect
"#<OpenStruct: #{@table.inspect}>" "#<OpenStruct: #{@table.inspect}>"
Expand Down

0 comments on commit 4085c51

Please sign in to comment.