Class: OpenObject

Inherits:
Hash show all
Defined in:
lib/more/facets/openobject.rb

Overview

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.

Direct Known Subclasses

OpenCascade

Constant Summary collapse

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

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Hash

#&, #*, #+, #-, #<<, #alias!, #argumentize, autonew, #delete_unless, #delete_values, #delete_values_at, #diff, #each_with_key, #except, #except!, #has_keys?, #has_only_keys?, #insert, #inverse, #join, #mash!, #normalize_keys, #normalize_keys!, #pairs_at, #rand_key, #rand_key!, #rand_pair, #rand_pair!, #rand_value, #rand_value!, #rekey, #rekey!, #replace_each, #restore_snapshot, #reverse_merge, #reverse_merge!, #select!, #shuffle, #shuffle!, #slice, #slice!, #stringify_keys, #stringify_keys!, #swap!, #swapkey!, #symbolize_keys, #symbolize_keys!, #take_snapshot, #to_console, #to_ostruct, #to_ostruct_recurse, #to_proc_with_reponse, #to_struct, #traverse, #traverse!, #update_each, #update_keys, #update_values, #variablize_keys, #variablize_keys!, #weave, zipnew, #|

Constructor Details

#initialize(hash = nil, &yld) ⇒ OpenObject

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)


78
79
80
81
# File 'lib/more/facets/openobject.rb', line 78

def initialize( hash=nil, &yld )
  super( &yld )
  hash.each { |k,v| define_slot(k,v) } if hash
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, arg = nil, &blk) ⇒ Object (protected)



187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/more/facets/openobject.rb', line 187

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

Class Method Details

.[](hash = nil) ⇒ Object



67
68
69
# File 'lib/more/facets/openobject.rb', line 67

def self.[](hash=nil)
  new(hash)
end

Instance Method Details

#==(other) ⇒ Object

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



151
152
153
154
# File 'lib/more/facets/openobject.rb', line 151

def ==( other )
  return false unless OpenObject === other
  super(other) #(other.send(:table))
end

#[](k) ⇒ Object



161
162
163
# File 'lib/more/facets/openobject.rb', line 161

def [](k)
  super(k.to_sym)
end

#[]=(k, v) ⇒ Object



156
157
158
159
# File 'lib/more/facets/openobject.rb', line 156

def []=(k,v)
  protect_slot(k)
  super(k.to_sym,v)
end

#as_hash!(&yld) ⇒ Object

Preform inplace action on OpenObject as if it were a regular Hash. – TODO Not so sure about #as_hash!. For starters if it doesn’t return a hash it will fail. TODO Replace by using #as(Hash). Perhaps as_hash and as_object shortcuts? Why? ++



145
146
147
# File 'lib/more/facets/openobject.rb', line 145

def as_hash!(&yld)
  replace(yld.call(to_hash))
end

#default!(default) ⇒ Object

Set the default value.



135
136
137
# File 'lib/more/facets/openobject.rb', line 135

def default!(default)
  self.default = default
end

#delete(key) ⇒ Object



129
130
131
# File 'lib/more/facets/openobject.rb', line 129

def delete(key)
  super(key.to_sym)
end

#each(&yld) ⇒ Object

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



106
# File 'lib/more/facets/openobject.rb', line 106

def each(&yld) super(&yld) end

#initialize_copy(orig) ⇒ Object



83
84
85
# File 'lib/more/facets/openobject.rb', line 83

def initialize_copy( orig )
  orig.each { |k,v| define_slot(k,v) }
end

#inspectObject

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



89
90
91
# File 'lib/more/facets/openobject.rb', line 89

def inspect
  "#<#{object_class}:#{object_hexid} #{super}>"
end

#merge(other) ⇒ Object

Merge one OpenObject with another creating a new OpenObject.



110
111
112
113
114
# File 'lib/more/facets/openobject.rb', line 110

def merge( other )
  d = dup
  d.send(:update, other)
  d
end

#to_aObject

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



95
# File 'lib/more/facets/openobject.rb', line 95

def to_a() super end

#to_hObject



97
# File 'lib/more/facets/openobject.rb', line 97

def to_h() {}.update(self) end

#to_hashObject



98
# File 'lib/more/facets/openobject.rb', line 98

def to_hash() {}.update(self) end

#to_openobjectObject



102
# File 'lib/more/facets/openobject.rb', line 102

def to_openobject() self end

#to_procObject



100
# File 'lib/more/facets/openobject.rb', line 100

def to_proc() super  end

#update(other) ⇒ Object

Update this OpenObject with another.



118
119
120
121
122
123
124
125
# File 'lib/more/facets/openobject.rb', line 118

def update( other )
  begin
    other.each { |k,v| define_slot(k,v) }
  rescue
    other = other.to_h
    retry
  end
end