OpenObject
OpenObject is very similar to Ruby‘s own OpenStruct, but it offers some useful advantages. With OpenStruct slots with the same name‘s as predefined Object methods can not be used. With OpenObject any slot can be defined, OpendObject is also a bit faster becuase it is based on a Hash, not method signitures.
Because OpenObject is a subclass of Hash, it can do just about everything a Hash can do, except that most public methods have been made protected and thus available only internally or via send.
OpenObject will also clobber any method for which a slot is defined. Even generally very important methods can be clobbered, like instance_eval. So be aware of this. OpenObject should be used in well controlled scenarios.
If you wish to pass an OpenObject to a routine that normal takes a Hash, but are uncertain it can handle the distictions properly you can convert easily to a Hash using to_hash! and the result will automatically be converted back to an OpenObject on return.
o = OpenObject.new(:a=>1,:b=>2) o.as_hash!{ |h| h.update(:a=>6) } o #=> #<OpenObject {:a=>6,:b=>2}>
Finally, unlike a regular Hash, all OpenObject‘s keys are symbols and all keys are converted to such using to_sym on the fly.
- ==
- []
- []
- []=
- as_hash!
- default!
- define_slot
- delete
- each
- fetch
- initialize_copy
- inspect
- merge
- method_missing
- new
- protect_slot
- store
- to_a
- to_h
- to_hash
- to_openobject
- to_proc
- update
PUBLIC_METHODS | = | /(^__|^instance_|^object_|^\W|^as$|^send$|^class$|\?$)/ |
[ show source ]
# File lib/more/facets/openobject.rb, line 88 def self.[](hash=nil) new(hash) end
Inititalizer for OpenObject is slightly differnt than that of Hash. It does not take a default parameter, but an initial priming Hash as with OpenStruct. The initializer can still take a default block however. To set the degault value use ++default!(value)++.
OpenObject(:a=>1).default!(0)
[ show source ]
# File lib/more/facets/openobject.rb, line 99 def initialize( hash=nil, &yld ) super( &yld ) hash.each { |k,v| define_slot(k,v) } if hash end
Check equality. (Should equal be true for Hash too?)
[ show source ]
# File lib/more/facets/openobject.rb, line 172 def ==( other ) return false unless OpenObject === other super(other) #(other.send(:table)) end
[ show source ]
# File lib/more/facets/openobject.rb, line 182 def [](k) super(k.to_sym) end
[ show source ]
# File lib/more/facets/openobject.rb, line 177 def []=(k,v) protect_slot(k) super(k.to_sym,v) end
Preform inplace action on OpenObject as if it were a regular Hash.
[ show source ]
# File lib/more/facets/openobject.rb, line 166 def as_hash!(&yld) replace(yld.call(to_hash)) end
Set the default value.
[ show source ]
# File lib/more/facets/openobject.rb, line 156 def default!(default) self.default = default end
[ show source ]
# File lib/more/facets/openobject.rb, line 150 def delete(key) super(key.to_sym) end
Iterate over each key-value pair. (Careful, this can be clobbered!)
[ show source ]
# File lib/more/facets/openobject.rb, line 127 def each(&yld) super(&yld) end
[ show source ]
# File lib/more/facets/openobject.rb, line 104 def initialize_copy( orig ) orig.each { |k,v| define_slot(k,v) } end
Object inspection. (Careful, this can be clobbered!)
[ show source ]
# File lib/more/facets/openobject.rb, line 110 def inspect "#<#{object_class}:#{object_hexid} #{super}>" end
Merge one OpenObject with another creating a new OpenObject.
[ show source ]
# File lib/more/facets/openobject.rb, line 131 def merge( other ) d = dup d.send(:update, other) d end
Conversion methods. (Careful, these can be clobbered!)
[ show source ]
# File lib/more/facets/openobject.rb, line 116 def to_a() super end
[ show source ]
# File lib/more/facets/openobject.rb, line 118 def to_h() {}.update(self) end
[ show source ]
# File lib/more/facets/openobject.rb, line 119 def to_hash() {}.update(self) end
[ show source ]
# File lib/more/facets/openobject.rb, line 123 def to_openobject() self end
[ show source ]
# File lib/more/facets/openobject.rb, line 121 def to_proc() super end
Update this OpenObject with another.
[ show source ]
# File lib/more/facets/openobject.rb, line 139 def update( other ) begin other.each { |k,v| define_slot(k,v) } rescue other = other.to_h retry end end
[ show source ]
# File lib/more/facets/openobject.rb, line 197 def define_slot( key, value=nil ) protect_slot( key ) self[key.to_sym] = value end
[ show source ]
# File lib/more/facets/openobject.rb, line 193 def fetch(k,*d,&b) super(k.to_sym,*d,&b) end
[ show source ]
# File lib/more/facets/openobject.rb, line 208 def method_missing( sym, arg=nil, &blk) type = sym.to_s[-1,1] key = sym.to_s.sub(/[=?!]$/,'').to_sym if type == '=' define_slot(key,arg) elsif type == '!' define_slot(key,arg) self else self[key] end end
[ show source ]
# File lib/more/facets/openobject.rb, line 202 def protect_slot( key ) (class << self; self; end).class_eval { protected key rescue nil } end
[ show source ]
# File lib/more/facets/openobject.rb, line 188 def store(k,v) super(k.to_sym,v) define_slot(k) end