Class OpenObject
In: lib/more/facets/openobject.rb
Parent: Hash

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.

Methods

==   []   []   []=   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  

Constants

PUBLIC_METHODS = /(^__|^instance_|^object_|^\W|^as$|^send$|^class$|\?$)/

Public Class methods

[Source]

    # File lib/more/facets/openobject.rb, line 88
88:   def self.[](hash=nil)
89:     new(hash)
90:   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)

[Source]

     # File lib/more/facets/openobject.rb, line 102
102:   def initialize( hash=nil, &yld )
103:     super( &yld )
104:     hash.each { |k,v| define_slot(k,v) } if hash
105:   end

Public Instance methods

Check equality. (Should equal be true for Hash too?)

[Source]

     # File lib/more/facets/openobject.rb, line 175
175:   def ==( other )
176:     return false unless OpenObject === other
177:     super(other) #(other.send(:table))
178:   end

[Source]

     # File lib/more/facets/openobject.rb, line 185
185:   def [](k)
186:     super(k.to_sym)
187:   end

[Source]

     # File lib/more/facets/openobject.rb, line 180
180:   def []=(k,v)
181:     protect_slot(k)
182:     super(k.to_sym,v)
183:   end

Preform inplace action on OpenObject as if it were a regular Hash.

[Source]

     # File lib/more/facets/openobject.rb, line 169
169:   def as_hash!(&yld)
170:     replace(yld.call(to_hash))
171:   end

Set the default value.

[Source]

     # File lib/more/facets/openobject.rb, line 159
159:   def default!(default)
160:     self.default = default
161:   end

[Source]

     # File lib/more/facets/openobject.rb, line 153
153:   def delete(key)
154:     super(key.to_sym)
155:   end

Iterate over each key-value pair. (Careful, this can be clobbered!)

[Source]

     # File lib/more/facets/openobject.rb, line 130
130:   def each(&yld) super(&yld) end

[Source]

     # File lib/more/facets/openobject.rb, line 107
107:   def initialize_copy( orig )
108:     orig.each { |k,v| define_slot(k,v) }
109:   end

Object inspection. (Careful, this can be clobbered!)

[Source]

     # File lib/more/facets/openobject.rb, line 113
113:   def inspect
114:     "#<#{object_class}:#{object_hexid} #{super}>"
115:   end

Merge one OpenObject with another creating a new OpenObject.

[Source]

     # File lib/more/facets/openobject.rb, line 134
134:   def merge( other )
135:     d = dup
136:     d.send(:update, other)
137:     d
138:   end

Conversion methods. (Careful, these can be clobbered!)

[Source]

     # File lib/more/facets/openobject.rb, line 119
119:   def to_a() super end

[Source]

     # File lib/more/facets/openobject.rb, line 121
121:   def to_h() {}.update(self) end

[Source]

     # File lib/more/facets/openobject.rb, line 122
122:   def to_hash() {}.update(self) end

[Source]

     # File lib/more/facets/openobject.rb, line 126
126:   def to_openobject() self end

[Source]

     # File lib/more/facets/openobject.rb, line 124
124:   def to_proc() super  end

Update this OpenObject with another.

[Source]

     # File lib/more/facets/openobject.rb, line 142
142:   def update( other )
143:     begin
144:       other.each { |k,v| define_slot(k,v) }
145:     rescue
146:       other = other.to_h
147:       retry
148:     end
149:   end

Protected Instance methods

[Source]

     # File lib/more/facets/openobject.rb, line 200
200:     def define_slot( key, value=nil )
201:       protect_slot( key )
202:       self[key.to_sym] = value
203:     end

[Source]

     # File lib/more/facets/openobject.rb, line 196
196:     def fetch(k,*d,&b)
197:       super(k.to_sym,*d,&b)
198:     end

[Source]

     # File lib/more/facets/openobject.rb, line 211
211:     def method_missing( sym, arg=nil, &blk)
212:       type = sym.to_s[-1,1]
213:       key = sym.to_s.sub(/[=?!]$/,'').to_sym
214:       if type == '='
215:         define_slot(key,arg)
216:       elsif type == '!'
217:         define_slot(key,arg)
218:         self
219:       else
220:         self[key]
221:       end
222:     end

[Source]

     # File lib/more/facets/openobject.rb, line 205
205:     def protect_slot( key )
206:       (class << self; self; end).class_eval {
207:         protected key rescue nil
208:       }
209:     end

[Source]

     # File lib/more/facets/openobject.rb, line 191
191:     def store(k,v)
192:       super(k.to_sym,v)
193:       define_slot(k)
194:     end

[Validate]