class Hashery::OpenHash
OpenHash
is a Hash
, but also supports open properties much like OpenStruct.
Only names that are name methods of Hash
can be used as open slots. To open a slot for a name that would otherwise be a method, the method needs to be made private. The `#open!` method can be used to handle this.
Examples
o = OpenHash.new o.open!(:send) o.send = 4
Attributes
If safe is set to true, then public methods cannot be overriden by hash keys.
Public Class Methods
Initialize new OpenHash
instance.
TODO: Maybe `safe` should be the first argument?
# File lib/hashery/open_hash.rb, line 33 def initialize(default=nil, safe=false, &block) @safe = safe super(*[default].compact, &block) end
Public Instance Methods
Make specific Hash
methods available for use that have previously opened.
methods - [Array<String,Symbol>] method names
Returns methods
.
# File lib/hashery/open_hash.rb, line 112 def close!(*methods) (class << self; self; end).class_eval{ public *methods } methods end
# File lib/hashery/open_hash.rb, line 120 def method_missing(s,*a, &b) type = s.to_s[-1,1] name = s.to_s.sub(/[!?=]$/, '') key = name.to_sym case type when '=' store(key, a.first) when '?' key?(key) when '!' # call an underlying private method # TODO: limit this to omitted methods (from included) ? __send__(name, *a, &b) else #if key?(key) retrieve(key) #else # super(s,*a,&b) #end end end
Open up a slot that that would normally be a Hash
method.
The only methods that can't be opened are ones starting with `__`.
methods - [Array<String,Symbol>] method names
Returns Array of slot names that were opened.
# File lib/hashery/open_hash.rb, line 72 def open!(*methods) # Only select string and symbols, any other type of key is allowed, # it just won't be accessible via dynamic methods. methods = methods.select{ |x| String === x || Symbol === x } if methods.any?{ |m| m.to_s.start_with?('__') } raise ArgumentError, "cannot open shadow methods" end # only public methods need be made protected methods = methods.map{ |x| x.to_sym } methods = methods & public_methods(true).map{ |x| x.to_sym } if @safe raise ArgumentError, "cannot set public method" unless methods.empty? else (class << self; self; end).class_eval{ protected *methods } end methods end
Is a slot open?
method - [String,Symbol] method name
Returns `true` or `false`.
# File lib/hashery/open_hash.rb, line 100 def open?(method) methods = public_methods(true).map{ |m| m.to_sym } ! methods.include?(method.to_sym) end
Index `value` to `key`. Unless safe mode, will also open up the key if it is not already open.
key - Index key to associate with value. value - Value to be associate with key.
Returns value
.
Hashery::CRUDHash#store
# File lib/hashery/open_hash.rb, line 58 def store(key, value) #open!(key) super(key, value) end