Class: BinData::LazyEvaluator

Inherits:
Object
  • Object
show all
Defined in:
lib/bindata/lazy.rb

Overview

A LazyEvaluator is bound to a data object. The evaluator will evaluate lambdas in the context of this data object. These lambdas are those that are passed to data objects as parameters, e.g.:

BinData::String.new(:value => lambda { %w{a test message}.join(" ") })

As a shortcut, :foo is the equivalent of lambda { foo }.

When evaluating lambdas, unknown methods are resolved in the context of the parent of the bound data object. Resolution is attempted firstly as keys in #parameters, and secondly as methods in this parent. This resolution propagates up the chain of parent data objects.

An evaluation will recurse until it returns a result that is not a lambda or a symbol.

This resolution process makes the lambda easier to read as we just write field instead of obj.field.

Instance Method Summary collapse

Constructor Details

#initialize(obj) ⇒ LazyEvaluator

Creates a new evaluator. All lazy evaluation is performed in the context of obj.



24
25
26
# File 'lib/bindata/lazy.rb', line 24

def initialize(obj)
  @obj = obj
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/bindata/lazy.rb', line 65

def method_missing(symbol, *args)
  return @overrides[symbol] if defined? @overrides and @overrides.has_key?(symbol)

  if @obj.parent
    eval_symbol_in_parent_context(symbol, args)
  else
    super
  end
end

Instance Method Details

#indexObject

Returns the index of this data object inside it’s nearest container array.

Raises:

  • (NoMethodError)


50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/bindata/lazy.rb', line 50

def index
  return @overrides[:index] if @overrides and @overrides.has_key?(:index)

  child = @obj
  parent = @obj.parent
  while parent
    if parent.respond_to?(:find_index_of)
      return parent.find_index_of(child)
    end
    child = parent
    parent = parent.parent
  end
  raise NoMethodError, "no index found"
end

#lazy_eval(val, overrides = nil) ⇒ Object



28
29
30
31
32
33
34
35
36
37
# File 'lib/bindata/lazy.rb', line 28

def lazy_eval(val, overrides = nil)
  @overrides = overrides if overrides
  if val.is_a? Symbol
    __send__(val)
  elsif val.respond_to? :arity
    instance_exec(&val)
  else
    val
  end
end

#parentObject

Returns a LazyEvaluator for the parent of this data object.



40
41
42
43
44
45
46
# File 'lib/bindata/lazy.rb', line 40

def parent
  if @obj.parent
    @obj.parent.lazy_evaluator
  else
    nil
  end
end