This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
require 'hashery/crud_hash'
|
||||
|
||||
module Hashery
|
||||
|
||||
# A PropertyHash is the same as a regular Hash except it strictly limits the
|
||||
# allowed keys.
|
||||
#
|
||||
# There are two ways to use it.
|
||||
#
|
||||
# 1) As an object in itself.
|
||||
#
|
||||
# h = PropertyHash.new(:a=>1, :b=>2)
|
||||
# h[:a] #=> 1
|
||||
# h[:a] = 3
|
||||
# h[:a] #=> 3
|
||||
#
|
||||
# But if we try to set key that was not fixed, then we will get an error.
|
||||
#
|
||||
# h[:x] = 5 #=> ArgumentError
|
||||
#
|
||||
# 2) As a superclass.
|
||||
#
|
||||
# class MyPropertyHash < PropertyHash
|
||||
# property :a, :default => 1
|
||||
# property :b, :default => 2
|
||||
# end
|
||||
#
|
||||
# h = MyPropertyHash.new
|
||||
# h[:a] #=> 1
|
||||
# h[:a] = 3
|
||||
# h[:a] #=> 3
|
||||
#
|
||||
# Again, if we try to set key that was not fixed, then we will get an error.
|
||||
#
|
||||
# h[:x] = 5 #=> ArgumentError
|
||||
#
|
||||
class PropertyHash < CRUDHash
|
||||
|
||||
#
|
||||
# Get a list of properties with default values.
|
||||
#
|
||||
# Returns [Hash] of properties and their default values.
|
||||
#
|
||||
def self.properties
|
||||
@properties ||= (
|
||||
parent = ancestors[1]
|
||||
if parent.respond_to?(:properties)
|
||||
parent.properties
|
||||
else
|
||||
{}
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
#
|
||||
# Define a property.
|
||||
#
|
||||
# key - Name of property.
|
||||
# opts - Property options.
|
||||
# :default - Default value of property.
|
||||
#
|
||||
# Returns default value.
|
||||
#
|
||||
def self.property(key, opts={})
|
||||
properties[key] = opts[:default]
|
||||
end
|
||||
|
||||
#
|
||||
# Initialize new instance of PropertyHash.
|
||||
#
|
||||
# properties - [Hash] Priming properties with default values, or
|
||||
# if it doesn't respond to #each_pair, a default object.
|
||||
# default_proc - [Proc] Procedure for default value of properties
|
||||
# for properties without specific defaults.
|
||||
#
|
||||
def initialize(properties={}, &default_proc)
|
||||
if properties.respond_to?(:each_pair)
|
||||
super(&default_proc)
|
||||
fixed = self.class.properties.merge(properties)
|
||||
fixed.each_pair do |key, value|
|
||||
store!(key, value)
|
||||
end
|
||||
else
|
||||
super(*[properties].compact, &default_proc)
|
||||
end
|
||||
end
|
||||
|
||||
# Alias original #store method and make private.
|
||||
alias :store! :store
|
||||
private :store!
|
||||
|
||||
#
|
||||
# Create a new property, on-the-fly.
|
||||
#
|
||||
# key - Name of property.
|
||||
# opts - Property options.
|
||||
# :default - Default value of property.
|
||||
#
|
||||
# Returns default value.
|
||||
#
|
||||
def property(key, opts={})
|
||||
if opts[:default]
|
||||
store!(key, opts[:default])
|
||||
else
|
||||
store!(key, retrieve(key))
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Store key value pair, ensuring the key is a valid property first.
|
||||
#
|
||||
# key - The `Object` to act as indexing key.
|
||||
# value - The `Object` to associate with key.
|
||||
#
|
||||
# Raises ArgumentError if key is not a valid property.
|
||||
#
|
||||
# Returns +value+.
|
||||
#
|
||||
def store(key, value)
|
||||
assert_key!(key)
|
||||
super(key, value)
|
||||
end
|
||||
|
||||
#
|
||||
#def update(h)
|
||||
# h.keys.each{ |k| assert_key!(k) }
|
||||
# super(h)
|
||||
#end
|
||||
|
||||
#
|
||||
#def merge!(h)
|
||||
# h.keys.each{ |k| assert_key!(k) }
|
||||
# super(h)
|
||||
#end
|
||||
|
||||
#
|
||||
# Like #store but takes a two-element Array of `[key, value]`.
|
||||
#
|
||||
# Returns value.
|
||||
#
|
||||
#def <<(a)
|
||||
# k,v = *a
|
||||
# store(k,v)
|
||||
#end
|
||||
|
||||
private
|
||||
|
||||
#
|
||||
# Asserta that a key is a defined property.
|
||||
#
|
||||
# Raises ArgumentError if key is not a property.
|
||||
#
|
||||
def assert_key!(key)
|
||||
unless key?(key)
|
||||
raise ArgumentError, "property is not defined -- #{key.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user