Class: Uniword::Template::VariableResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/uniword/template/variable_resolver.rb

Overview

Resolves variable expressions to values from data context.

Handles nested property access (e.g., “chapter.number”) and conditional evaluation. Works with both Hash and object data sources.

Responsibility: Variable resolution only Single Responsibility Principle: Does NOT parse, render, or validate

Examples:

Resolve simple variable

resolver = VariableResolver.new(title: "My Document")
resolver.resolve("title") # => "My Document"

Resolve nested property

data = { chapter: { number: "5.1" } }
resolver = VariableResolver.new(data)
resolver.resolve("chapter.number") # => "5.1"

Resolve from object

class Chapter
  attr_reader :number
  def initialize(num)
    @number = num
  end
end
resolver = VariableResolver.new(Chapter.new("5.1"))
resolver.resolve("number") # => "5.1"

Instance Method Summary collapse

Constructor Details

#initialize(data, context = {}) ⇒ VariableResolver

Initialize resolver with data context

Parameters:

  • data (Hash, Object)

    Data source for variable resolution

  • context (Hash) (defaults to: {})

    Additional context variables



36
37
38
39
# File 'lib/uniword/template/variable_resolver.rb', line 36

def initialize(data, context = {})
  @data = data
  @context = context
end

Instance Method Details

#evaluate(condition) ⇒ Boolean

Evaluate conditional expression

Supports:

  • Simple truthiness: “has_annexes”

  • Comparisons: “count > 5”, “status == ‘active’”

Parameters:

  • condition (String)

    Condition expression

Returns:

  • (Boolean)

    Evaluation result



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/uniword/template/variable_resolver.rb', line 75

def evaluate(condition)
  return false if condition.nil? || condition.empty?

  # Simple variable existence/truthiness check
  if condition.match?(/^\w+(\.\w+)*$/)
    value = resolve(condition)
    return !!value
  end

  # Comparison operators - order matters, check >= and <= before > and <
  match = condition.match(/(.+?)\s*(>=|<=|==|!=|>|<)\s*(.+)/)
  if match
    left_expr = match[1].strip
    operator = match[2]
    right_expr = match[3].strip

    left = resolve(left_expr)
    right = parse_literal(right_expr)

    evaluate_comparison(left, operator, right)
  else
    false
  end
end

#resolve(expression) ⇒ Object

Resolve variable expression to value

Supports dot notation for nested properties:

  • “title” => @data or @data.title

  • “chapter.number” => @data[:number] or @data.chapter.number

Parameters:

  • expression (String)

    Variable expression (e.g., “title”, “chapter.number”)

Returns:

  • (Object)

    Resolved value or nil if not found



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/uniword/template/variable_resolver.rb', line 49

def resolve(expression)
  return nil if expression.nil? || expression.empty?

  parts = expression.to_s.split(".")

  # Start with root data
  value = @data

  # Navigate through each part
  parts.each do |part|
    break if value.nil?

    value = navigate_property(value, part)
  end

  value
end