Class: Stunted::FunctionalHash

Inherits:
Hash
  • Object
show all
Extended by:
ShapeableClassMethods
Includes:
Shapeable
Defined in:
lib/stunted/mocking.rb,
lib/stunted/functional-hash.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ShapeableClassMethods

shaped_class

Methods included from Shapeable

#become

Constructor Details

#initialize(hash = {}) ⇒ FunctionalHash

Returns a new instance of FunctionalHash.



7
8
9
10
11
12
13
14
15
16
17
# File 'lib/stunted/functional-hash.rb', line 7

def initialize(hash = {})
  hash.each do | k, v |
    self[k] = v
    if k.is_a?(Symbol)
      if self.respond_to?(k)
        $stderr.puts("Warning: #{k.inspect} overrides existing Hash method.")
      end
      instance_eval("def #{k}; self[#{k.inspect}]; end")
    end
  end
end

Class Method Details

.make_maker(*shapes) ⇒ Object



80
81
82
83
# File 'lib/stunted/functional-hash.rb', line 80

def self.make_maker(*shapes)
  klass = shaped_class(*shapes)
  ->(inits={}) { klass.new(inits) }
end

Instance Method Details

#-(keys) ⇒ Object



67
68
69
70
# File 'lib/stunted/functional-hash.rb', line 67

def -(keys)
  keys = [keys] unless keys.respond_to?(:first)
  remove(*keys)
end

#[](key) ⇒ Object



72
73
74
# File 'lib/stunted/functional-hash.rb', line 72

def [](key)
  fetch(key, nil)
end

#change_within(*args) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/stunted/functional-hash.rb', line 41

def change_within(*args)
  if (args.first.is_a? Hash)
    merge(args.first)
  else
    key = args.first
    rest = args[1..-1]
    merge(key => fetch(key).change_within(*rest))
  end
end

#component(hash) ⇒ Object

For now, just one pair



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/stunted/functional-hash.rb', line 85

def component(hash)   # For now, just one pair
  field = hash.keys.first
  shape = hash.values.first
  secondary_module = Module.new
  shape.instance_methods.each do | meth |
    defn = "def #{meth}(*args)
              merge(#{field.inspect} => self.#{field}.#{meth}(*args))
            end"
    secondary_module.module_eval(defn)
  end
  merge(field => self[field].become(shape)).become(secondary_module)
end

#fetch(key, *args, &block) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/stunted/functional-hash.rb', line 19

def fetch(key, *args, &block)
  current = super(key, *args, &block)
  if current.is_a?(Proc)
    if current.arity == 0
      self[key] = current.()
    else
      self[key] = current.(self)
    end
  else
    current
  end
end

#merge(hash) ⇒ Object Also known as: +



32
33
34
# File 'lib/stunted/functional-hash.rb', line 32

def merge(hash)
  self.class.new(super(hash))
end

#only(*keys) ⇒ Object



76
77
78
# File 'lib/stunted/functional-hash.rb', line 76

def only(*keys)
  self.class[*keys.zip(self.values_at(*keys)).flatten(1)]
end

#remove(*keys) ⇒ Object



51
52
53
54
55
# File 'lib/stunted/functional-hash.rb', line 51

def remove(*keys)
  new_hash = dup
  keys.each { | key | new_hash.send(:delete, key) }
  self.class.new(new_hash)
end

#remove_within(*args) ⇒ Object



57
58
59
60
61
62
63
64
65
# File 'lib/stunted/functional-hash.rb', line 57

def remove_within(*args)
  key = args.first
  rest = args[1..-1]
  if (args.count <= 1)
    remove(key)
  else
    merge(key => fetch(key).remove_within(*rest))
  end
end

#transform(symbol) ⇒ Object



37
38
39
# File 'lib/stunted/functional-hash.rb', line 37

def transform(symbol)
  merge(symbol => yield(self[symbol]))
end

#with_replacement_methods(hash, &block) ⇒ Object



17
18
19
# File 'lib/stunted/mocking.rb', line 17

def with_replacement_methods(hash, &block)
  self.class.with_replacement_methods(hash, &block)
end