class FlexHash

Like a combination of HashWithIndifferentAccess, OpenStruct, plus it takes an integer and tries looking it up positionally. (bleh, like php’s but a little more buggy. I know I know- but it’s for a very specific purpose).

Mostly cribbed from rubinius’s ostruct: github.com/rubysl/rubysl-ostruct/blob/2.0/lib/rubysl/ostruct/ostruct.rb with just the [] access function changed and method_missing changed so it delegates unfound things to the underlying table.

Public Class Methods

[](*arr_const) click to toggle source
# File lib/flexhash.rb, line 10
def self.[](*arr_const)
  self.new(arr_const.flatten)
end
new(constructor=nil) click to toggle source
# File lib/flexhash.rb, line 14
def initialize(constructor=nil)
  @table = {}
  if constructor.respond_to?(:each_pair)
    constructor.each_pair{|k,v| self[k.to_sym] = v }
  elsif constructor.respond_to?(:each_slice)
    constructor.each_slice(2){|k,v| self[k.to_sym] = v }
  elsif constructor != nil
    raise ArgumentError, "cannot initialize flexhash with #{constructor}", caller(3)
  end
end

Public Instance Methods

<<(kv) click to toggle source
# File lib/flexhash.rb, line 104
def <<(kv)
  name, value = kv
  self[name] = value
end
==(other) click to toggle source
# File lib/flexhash.rb, line 143
def ==(other)
  return false unless other.kind_of?(OpenStruct)
  @table == other.table
end
[](name) click to toggle source
# File lib/flexhash.rb, line 88
def [](name)
  if Integer === name
    @table[name] || @table[@table.keys[name]]
  else
    res = @table[name] || @table[name.try(:to_sym)]
    return res if res
    res = @table.select{|k,v| name === k}
    return res.values[0] if res.size == 1
    res
  end
end
[]=(name, value) click to toggle source
# File lib/flexhash.rb, line 100
def []=(name, value)
  modifiable[new_flexhash_member(name)] = value
end
delete_field(name) click to toggle source
# File lib/flexhash.rb, line 109
def delete_field(name)
  sym = name.to_sym
  singleton_class.__send__(:remove_method, sym, "#{name}=")
  @table.delete sym
end
each_pair() { |p| ... } click to toggle source
# File lib/flexhash.rb, line 35
def each_pair
  return to_enum __method__ unless block_given?
  @table.each_pair { |p| yield p }
end
eql?(other) click to toggle source
# File lib/flexhash.rb, line 148
def eql?(other)
  return false unless other.kind_of?(OpenStruct)
  @table.eql?(other.table)
end
hash() click to toggle source
# File lib/flexhash.rb, line 153
def hash
  @table.hash
end
initialize_copy(orig) click to toggle source
Calls superclass method
# File lib/flexhash.rb, line 25
def initialize_copy(orig)
  super
  @table = @table.dup
  @table.each_key { |key| new_flexhash_member(key) }
end
inspect() click to toggle source
# File lib/flexhash.rb, line 117
def inspect
  str = "#<#{self.class}"

  ids = (Thread.current[InspectKey] ||= [])
  if ids.include?(object_id)
    return str << ' ...>'
  end

  ids << object_id
  begin
    first = true
    for k,v in @table
      str << "," unless first
      first = false
      str << " #{k}=#{v.inspect}"
    end
    return str << '>'
  ensure
    ids.pop
  end
end
Also aliased as: to_s
marshal_dump() click to toggle source
# File lib/flexhash.rb, line 40
def marshal_dump
  @table
end
marshal_load(x) click to toggle source
# File lib/flexhash.rb, line 44
def marshal_load(x)
  @table = x
  @table.each_key{|key| new_flexhash_member(key)}
end
method_missing(mid, *args, &block) click to toggle source
# File lib/flexhash.rb, line 69
def method_missing(mid, *args, &block)
  mname = mid.id2name
  len = args.length
  if mname.chomp!('=')
    if len != 1
      raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
    end
    modifiable[new_flexhash_member(mname)] = args[0]
  elsif len == 0
    res = @table[mid] || @table.send(mid, *args, &block)
    res = FlexHash.new(res) if res.instance_of? Hash
    res
  else
    res = @table.send(mid, *args, &block)
    res = FlexHash.new(res) if res.instance_of? Hash
    res
  end
end
to_h() click to toggle source
# File lib/flexhash.rb, line 31
def to_h
  @table.dup
end
to_s()
Alias for: inspect

Protected Instance Methods

modifiable() click to toggle source
# File lib/flexhash.rb, line 49
def modifiable
  begin
    @modifiable = true
  rescue
    raise TypeError, "can't modify frozen #{self.class}", caller(3)
  end
  @table
end
new_flexhash_member(name) click to toggle source
# File lib/flexhash.rb, line 59
def new_flexhash_member(name)
  name = name.to_sym
  unless respond_to?(name)
    define_singleton_method(name) { @table[name] }
    define_singleton_method("#{name}=") { |x| modifiable[name] = x }
  end
  name
end