class Octothorpe

A very simple hash-like class that borrows a little from OpenStruct, etc.

Meant to facilitate message-passing between classes.

Simple example:

ot = Octothorpe.new(one: 1, "two" => 2, "weird key" => 3)
ot.>>.one            # -> 1
ot.>>.two            # -> 2
ot.get("weird key")  # -> 3

With guard conditions:

ot = Octotghorpe.new(one: 1, "two" => 2)
ot.guard(Array, :three)
ot.freeze       # optional step - makes OT truly read-only
ot.>>.three     # -> []
ot.>>.three[9]  # valid (of course; returns nil)

Octothorpe additionally responds to the following methods exactly as a Hash would:

empty?, has_key?, has_value?, include?
each,   each_key, each_value, keys,    values
select, map,      reject,     inject
merge,  <, >< ==, >+, <=

Constants

VERSION

Gem version number

Public Class Methods

ot = Octothrpe.new(hash) click to toggle source

Initialise an Octothorpe object by passing it a hash.

You can create an empty OT by calling Octothorpe.new, but there's probably little utility in that, given that it is read-only.

If you pass anything other than nil or something OT can treat as a Hash, you will cause an Octothorpe::BadHash exception.

# File lib/octothorpe.rb, line 89
def initialize(hash=nil)
  @store = Storage.new( symbol_hash(hash || {}) )
  @inner_hash = @store.octothorpe_store
end

Public Instance Methods

<(other) click to toggle source
# File lib/octothorpe.rb, line 208
def <(other);  compare_as_hash(other, :<);  end
<=(other) click to toggle source
# File lib/octothorpe.rb, line 211
def <=(other); compare_as_hash(other, :<=); end
==(other) click to toggle source

Resolve some of the standard comparisons (with an OT or a hash)

# File lib/octothorpe.rb, line 207
def ==(other); compare_as_hash(other, :==); end
>(other) click to toggle source
# File lib/octothorpe.rb, line 209
def >(other);  compare_as_hash(other, :>);  end
>=(other) click to toggle source
# File lib/octothorpe.rb, line 210
def >=(other); compare_as_hash(other, :>=); end
>>.keyname click to toggle source

You can use >> to access member objects in somewhat the same way as an OpenStruct.

ot = Octothorpe.new(one: 1, "two" => 2)
ot.>>.one  # -> 1

This will not work for members that have keys with spaces in, keys which have the same name as methods on Object, or keys that aren't String or Symbol. Use get for those.

# File lib/octothorpe.rb, line 107
def >>; @store; end
ot[key]
Alias for: get
get(key) click to toggle source

You can use get to access member object values instead of the >> syntax.

Unlike >>, this works for keys with spaces, or keys that have the same name as methods on Object.

# File lib/octothorpe.rb, line 121
def get(key); @store.octothorpe_store[octokey key]; end
Also aliased as: send, []
guard( class, key [, key, ...] ) click to toggle source
guard( key, [,key, ...] ) {|k| ... }

Guarantees the initial state of a memnber. Each key that is not already present will be set to <class>.new. Has no effect if key is already present. Class must be some class Thing that can respond to a vanilla Thing.new.

Alternatively, for the block form, the key is passed to the block, and the value of the key becomes the return value of the block … but again, ONLY if the key is not already set.

Note that this is the only time that you can modify an Octothorpe object once it is created. If you call freeze on an it, it will become genuinely read-only, and any call to guard from then on will raise Octothorpe::Frozen.

# File lib/octothorpe.rb, line 149
def guard(*args)
  raise Frozen if self.frozen?

  klass = args.shift unless block_given?
  keys  = args.map{|k| octokey k}

  if block_given?
    keys.each{|k| @store.octothorpe_store[k] ||= yield k }
  else
    keys.each{|k| @store.octothorpe_store[k] ||= klass.new }
  end

  self
end
inspect() click to toggle source

Inspect exposes a view of the inner hash

# File lib/octothorpe.rb, line 217
def inspect
  "#<Octothorpe#{@store.octothorpe_store.inspect}>"
end
merge(other) → new_ot click to toggle source
merge(other){|key, oldval, newval| block} → new_ot

Exactly as Hash.merge, but returns a new Octothorpe object.

You may pass a hash or an octothorpe. Raises Octothorpe::BadHash if it is anything else.

# File lib/octothorpe.rb, line 174
def merge(other)
  thisHash  = @store.octothorpe_store
  otherHash = symbol_hash(other)

  merged = 
    if block_given?
      thisHash.merge(otherHash) {|key,old,new| yield key, old, new }
    else
      thisHash.merge(otherHash)
    end

  Octothorpe.new(merged)
end
send(key)
Alias for: get
to_h() click to toggle source

Returns a hash of the object.

# File lib/octothorpe.rb, line 130
def to_h; @store.octothorpe_store; end
whitelist(:one, :two, :three) → new_ot click to toggle source

Return an Octothorpe containing only these keys.

If you name a key that is missing, that key will also be missing in the output; use Guard if that's not what you want.

# File lib/octothorpe.rb, line 198
def whitelist(*keys)
  Octothorpe.new @inner_hash.select{|k,_| symbol_hash(keys).include? k}
end

Private Instance Methods

compare_as_hash(other, method) click to toggle source

Given an 'other' - Hash or OT - render both self and other down to a hash then run the given comparason on them and return the result

# File lib/octothorpe.rb, line 243
def compare_as_hash(other, method)
  thisHash  = @store.octothorpe_store.to_h
  otherHash = symbol_hash(other)
  thisHash.send(method, otherHash)
end
octokey(thing) click to toggle source

Munge a potential key so we can use it

# File lib/octothorpe.rb, line 253
def octokey(thing)
  thing.is_a?(String) ? thing.to_sym : thing
end
symbol_hash(thing) click to toggle source

Try to return thing as a hash with symbols for keys

# File lib/octothorpe.rb, line 228
def symbol_hash(thing)
  if thing.kind_of?(Octothorpe)
    thing.to_h
  else
    thing.each_with_object({}) {|(k,v),m| m[octokey k] = v }
  end
rescue
  raise BadHash, $!
end