class Canister

A container that registers keys to values that are resolved at runtime. This allows for out-of-order declaration, automatic dependency resolution, and–upon redeclaration–automatic dependency cache invalidation.

Constants

VERSION

Attributes

dependents[R]
registry[R]
resolved[R]
stack[R]

Public Class Methods

new() { |self| ... } click to toggle source
# File lib/canister.rb, line 11
def initialize
  @stack = []
  @registry = {}
  @resolved = {}
  @dependents = Hash.new do |hash, key|
    hash[key] = []
  end
  yield self if block_given?
end

Public Instance Methods

[](key)
Alias for: resolve
keys() click to toggle source
# File lib/canister.rb, line 63
def keys
  registry.keys
end
method_missing(method, *args, &block) click to toggle source

We override method_missing to enable dot notation for accessing registered values.

Calls superclass method
# File lib/canister.rb, line 23
def method_missing(method, *args, &block)
  if handles?(method)
    resolve(method)
  else
    super(method, *args, block)
  end
end
register(key, &block) click to toggle source

Register a value to a key by passing a block. Note that the value will be that returned by the block. If the key has been registered before, the old registration is overwritten. Dependents of the original registration are automatically invalidated. @param key [Symbol] @yield self [Container] Yields this container. @return the value defined in the block

# File lib/canister.rb, line 45
def register(key, &block)
  invalidate(key) if registered?(key)
  registry[key.to_sym] = block
  self
end
resolve(key) click to toggle source

Recursively resolves the object that was registered to the key. This value is memoized. @param key [Symbol]

# File lib/canister.rb, line 54
def resolve(key)
  add_dependent(key)
  stack << key
  value = resolved[key.to_sym] ||= registry[key.to_sym].call(self)
  stack.pop
  value
end
Also aliased as: []
respond_to_missing?(method, include_all = false) click to toggle source

We override respond_to? to enable dot notation for accessing registered values.

Calls superclass method
# File lib/canister.rb, line 33
def respond_to_missing?(method, include_all = false)
  handles?(method) || super(method, include_all)
end

Private Instance Methods

add_dependent(key) click to toggle source
# File lib/canister.rb, line 75
def add_dependent(key)
  unless stack.empty?
    dependents[key.to_sym] << stack.last
  end
end
handles?(method) click to toggle source
# File lib/canister.rb, line 71
def handles?(method)
  registered?(method)
end
invalidate(key, first = true) click to toggle source
# File lib/canister.rb, line 89
def invalidate(key, first = true)
  unresolve(key)
  dependents[key.to_sym]
    .each {|child| invalidate(child, false) }
  dependents.delete(key.to_sym) if first
end
registered?(key) click to toggle source
# File lib/canister.rb, line 81
def registered?(key)
  registry.key?(key.to_sym)
end
unresolve(key) click to toggle source
# File lib/canister.rb, line 85
def unresolve(key)
  resolved.delete(key.to_sym)
end