Class: Hashery::OpenHash
- Defined in:
- lib/hashery/open_hash.rb
Overview
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.
Direct Known Subclasses
Constant Summary
Constants inherited from CRUDHash
Instance Attribute Summary collapse
-
#safe ⇒ Object
If safe is set to true, then public methods cannot be overriden by hash keys.
Instance Method Summary collapse
-
#close!(*methods) ⇒ Object
Make specific Hash methods available for use that have previously opened.
-
#initialize(default = nil, safe = false, &block) ⇒ OpenHash
constructor
Initialize new OpenHash instance.
- #method_missing(s, *a, &b) ⇒ Object
-
#open!(*methods) ⇒ Array
(also: #omit!)
Open up a slot that that would normally be a Hash method.
-
#open?(method) ⇒ Boolean
Is a slot open?.
-
#store(key, value) ⇒ Object
Index ‘value` to `key`.
Methods inherited from CRUDHash
#<<, #[], [], #[]=, auto, #cast, #cast_key, #default_proc, #delete, #each, #fetch, #key?, #key_proc, #key_proc=, #merge, #read, #replace, #retrieve, #to_hash, #update, #values_at
Methods inherited from Hash
create, #rekey, #rekey!, #retrieve, #to_hash, #to_stash
Constructor Details
#initialize(default = nil, safe = false, &block) ⇒ OpenHash
Maybe ‘safe` should be the first argument?
Initialize new OpenHash instance.
33 34 35 36 |
# File 'lib/hashery/open_hash.rb', line 33 def initialize(default=nil, safe=false, &block) @safe = safe super(*[default].compact, &block) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(s, *a, &b) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# 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 |
Instance Attribute Details
#safe ⇒ Object
If safe is set to true, then public methods cannot be overriden by hash keys.
42 43 44 |
# File 'lib/hashery/open_hash.rb', line 42 def safe @safe end |
Instance Method Details
#close!(*methods) ⇒ Object
Make specific Hash methods available for use that have previously opened.
112 113 114 115 |
# File 'lib/hashery/open_hash.rb', line 112 def close!(*methods) (class << self; self; end).class_eval{ public *methods } methods end |
#open!(*methods) ⇒ Array Also known as: omit!
Open up a slot that that would normally be a Hash method.
The only methods that can’t be opened are ones starting with ‘__`.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# 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 |
#open?(method) ⇒ Boolean
Is a slot open?
100 101 102 103 |
# 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 |
#store(key, value) ⇒ Object
Index ‘value` to `key`. Unless safe mode, will also open up the key if it is not already open.
58 59 60 61 |
# File 'lib/hashery/open_hash.rb', line 58 def store(key, value) #open!(key) super(key, value) end |