class Dagger::Default

Default value generator for a dictionary

Attributes

cached[W]
default_proc[R]

Public Class Methods

new(graph, vertex) → Dagger::Default click to toggle source
new(*, cached: false)
new(*, rule_prefix: '_default')

Initialize a default value generator for a vertex

# File lib/dagger/default.rb, line 23
def initialize(vertex,
               cached: false,
               fallback: nil,
               rule_prefix: '_default')
  @vertex = vertex
  @cached = cached
  @fallback = fallback
  @rule_prefix = rule_prefix.to_key_path
  @default_proc = ->(tree, key) { generate(tree, key) }
  @locks = Set[]
end
proc(*args, **kwargs) click to toggle source
# File lib/dagger/default.rb, line 13
def self.proc(*args, **kwargs)
  new(*args, **kwargs).default_proc
end

Public Instance Methods

cached? → bool click to toggle source

Verify state of caching of future values

# File lib/dagger/default.rb, line 41
def cached?
  !(!@cached)
end
generate(tree, key) → value || KeyError click to toggle source

Generate a default value for a key, possibly caching the result in the tree.

Raises a KeyError if the default value cannot be generated. Raises a RuntimeError in case of a deadlock for key.

# File lib/dagger/default.rb, line 54
def generate(tree, key)
  key = key.to_key_path
  with_locked_key(key) { |locked_key| cached_value(tree, locked_key) }
end

Private Instance Methods

cached_value(tree, key) → value || KeyError click to toggle source

Return the default value for key, caching it in tree if enabled.

# File lib/dagger/default.rb, line 77
def cached_value(tree, key)
  result = process(key)
  return result unless result.nil?

  result = @fallback&.[](key)
ensure
  tree[key] = result if cached? && !result.nil?
end
camelize(string) click to toggle source

Convert snake_case to CamelCase

# File lib/dagger/default.rb, line 130
def camelize(string)
  string.split('_').map!(&:capitalize).join
end
default_rules(key) → Array of Hash click to toggle source

Return the default value generation rules for a key.

# File lib/dagger/default.rb, line 108
def default_rules(key)
  @vertex.fetch(@rule_prefix + key, nil)
end
yield → value || KeyError click to toggle source

Process value generation rules for context, raising a KeyError if a value could not be generated. Catches :result thows from rule processing.

# File lib/dagger/default.rb, line 92
def process(key)
  catch do |ball|
    default_rules(key)&.each do |rule|
      context = Context.new(dictionary: @vertex,
                            result: ball,
                            vertex: @vertex)
      process_rule_chain(rule, context)
    end
    nil
  end
end
process_rule_chain(rule_chain, context) click to toggle source

Process the methods in a rule chain

# File lib/dagger/default.rb, line 116
def process_rule_chain(rule_chain, context)
  catch do |ball|
    context.stop = ball
    rule_chain.each do |key, arg|
      klass = Dagger::Generate.const_get(camelize(key))
      klass[context, arg, &->(value) { throw context.result, value }]
    end
  end
end
with_locked_key(key &->(locked_key)) → result click to toggle source

Process a block with mutex for key

# File lib/dagger/default.rb, line 65
def with_locked_key(key)
  raise %(deadlock detected: "#{key}") unless @locks.add?(key)

  yield(key)
ensure
  @locks.delete(key)
end