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.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(obj) ⇒ LazyEvaluator

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



44
45
46
# File 'lib/bindata/lazy.rb', line 44

def initialize(obj)
  @obj = obj
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object



85
86
87
88
89
90
91
92
93
# File 'lib/bindata/lazy.rb', line 85

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

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

Class Method Details

.eval(obj, val, overrides = nil) ⇒ Object

Lazily evaluates val in the context of obj, with possibility of overrides.



25
26
27
28
29
30
31
32
# File 'lib/bindata/lazy.rb', line 25

def eval(obj, val, overrides = nil)
  if can_eval?(val)
    env = self.new(obj)
    env.lazy_eval(val, overrides)
  else
    val
  end
end

Instance Method Details

#indexObject

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

Raises:

  • (NoMethodError)


70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/bindata/lazy.rb', line 70

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



48
49
50
51
52
53
54
55
56
57
# File 'lib/bindata/lazy.rb', line 48

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.



60
61
62
63
64
65
66
# File 'lib/bindata/lazy.rb', line 60

def parent
  if @obj.parent
    LazyEvaluator.new(@obj.parent)
  else
    nil
  end
end