Class: Droom::LazyHash

Inherits:
Hash
  • Object
show all
Defined in:
lib/droom/lazy_hash.rb

Overview

LazyHash is a recursive hash descendant that accepts keys in the form ‘key:subkey:subsubkey` and populates nested hashes accordingly.

In droom this mechanism is used to manage the default values that sit behind user preferences. The motive is to match the ‘User#pref(key)` interface, with concatenated keys designating namespaced values:

LazyHash.set("key:subkey:otherkey:something", "hippopotamus")
  => {:key => {:subkey => {:otherkey => {:something => "hippopotamus"}}}}

LazyHash.get("key:subkey:otherkey") => {:something => "hippopotamus"}
LazyHash.get("key:subkey:otherkey:something") => "hippopotamus"

An unset value will always return nil. A set value may be false. You may want to test for the difference.

NB. keys are always symbolized.

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ LazyHash

Returns a new instance of LazyHash.



22
23
24
25
26
27
28
# File 'lib/droom/lazy_hash.rb', line 22

def initialize(*args)
  hash = args.extract_options!
  super
  hash.each_pair do |k,v|
    self[k] = v.is_a?(Hash) ? Droom::LazyHash.new(v) : v
  end
end

Instance Method Details

#get(path) ⇒ Object

get will return the value in the named bucket. The bucket is designated by a key that can either be simple or the dot.separated path to a nested hash.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/droom/lazy_hash.rb', line 37

def get(path)
  key, subkeys = split_path(path)
  if subkeys.any?
    if self[key].is_a?(Droom::LazyHash)
      self[key].get(subkeys)
    else
      nil
    end
  elsif self.key?(key)
    self[key]
  else
    nil
  end
end

#inspectObject



30
31
32
# File 'lib/droom/lazy_hash.rb', line 30

def inspect
  "lazyhash: #{super}"
end

#set(path, value) ⇒ Object

set will set the value at the named bucket. Note that you should only ever do this from an initializer or some other thread-global event that can be relied upon always to have run. Never call LazyHash#set at runtime unless what you want is a local, non-thread-global nested hash construction.



56
57
58
59
60
61
62
63
64
# File 'lib/droom/lazy_hash.rb', line 56

def set(path, value)
  key, subkeys = split_path(path)
  if subkeys.any?
    self[key] ||= Droom::LazyHash.new({})
    self[key].set(subkeys, value)
  else
    self[key] = value
  end
end

#split_path(key) ⇒ Object



67
68
69
70
# File 'lib/droom/lazy_hash.rb', line 67

def split_path(key)
  keys = key.is_a?(Array) ? key : key.to_s.split('.')
  keys.any? ? [keys.shift.to_sym, keys] : [nil, []]
end