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

safe[RW]

If safe is set to true, then public methods cannot be overriden by hash keys.

Public Class Methods

new(default=nil, safe=false, &block) click to toggle source

Initialize new OpenHash instance.

TODO: Maybe ‘safe` should be the first argument?

Calls superclass method
# 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

close!(*methods) click to toggle source

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
method_missing(s,*a, &b) click to toggle source
# 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
omit!(*methods)

@deprecated

Alias for: open!
open!(*methods) click to toggle source

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
Also aliased as: omit!
open?(method) click to toggle source

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
store(key, value) click to toggle source

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.

Calls superclass method Hashery::CRUDHash#store
# File lib/hashery/open_hash.rb, line 58
def store(key, value)
  #open!(key)
  super(key, value)
end