Class: Canister

Inherits:
Object
  • Object
show all
Defined in:
lib/canister.rb,
lib/canister/version.rb

Overview

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.

Constant Summary collapse

VERSION =
"0.9.2"

Instance Method Summary collapse

Constructor Details

#initialize {|_self| ... } ⇒ Canister

Returns a new instance of Canister.

Yields:

  • (_self)

Yield Parameters:

  • _self (Canister)

    the object that the method was called on



11
12
13
14
15
16
17
18
19
20
# File 'lib/canister.rb', line 11

def initialize
  @stack = []
  @registry = {}
  @resolved = {}
  @dependents = Hash.new do |hash, key|
    hash[key] = []
  end
  @mutex = Mutex.new
  yield self if block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

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



24
25
26
27
28
29
30
# File 'lib/canister.rb', line 24

def method_missing(method, *args, &block)
  if handles?(method)
    resolve(method)
  else
    super(method, *args, block)
  end
end

Instance Method Details

#keysObject



79
80
81
# File 'lib/canister.rb', line 79

def keys
  registry.keys
end

#register(key, &block) ⇒ Object

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.

Parameters:

  • key (Symbol)

Returns:

  • the value defined in the block



54
55
56
57
58
59
60
61
# File 'lib/canister.rb', line 54

def register(key, &block)
  key = key.to_sym
  synchronize do
    invalidate(key) if registered?(key)
    registry[key] = block
  end
  self
end

#resolve(key) ⇒ Object Also known as: []

Recursively resolves the object that was registered to the key. This value is memoized.

Parameters:

  • key (Symbol)


66
67
68
69
70
71
72
73
74
75
76
# File 'lib/canister.rb', line 66

def resolve(key)
  key = key.to_sym
  value = nil
  synchronize do
    add_dependent(key)
    stack << key
    value = resolved[key] ||= registry[key].call(self)
    stack.pop
  end
  value
end

#respond_to_missing?(method, include_all = false) ⇒ Boolean

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

Returns:

  • (Boolean)


34
35
36
# File 'lib/canister.rb', line 34

def respond_to_missing?(method, include_all = false)
  handles?(method) || super(method, include_all)
end

#synchronize(&block) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/canister.rb', line 38

def synchronize(&block)
  if @mutex.owned?
    yield
  else
    @mutex.synchronize(&block)
  end
end