class PoiseDerived::LazyAttribute

A class to lazily evaluate node attributes either from format strings or code blocks.

@example Cookbook attributes file

default['mycookbook']['version'] = '1.0'
default['mycookbook']['url'] = lazy 'https://example.com/myapp-%{mycookbook.version}.zip'

Constants

FORMAT_STRING_REGEXP

Parser regexp for format strings. @api private

Public Class Methods

new(node, str=nil, &block) click to toggle source
# File lib/poise_derived/lazy_attribute.rb, line 30
def initialize(node, str=nil, &block)
  unless (!!str) ^ (!!block)
   raise ArgumentError.new('Either a string or block must be passed when creating a lazy attribute')
  end
  @node = node
  @value = str || block
end

Public Instance Methods

==(other) click to toggle source

Specifically delegate == because not caught by method_missing. @api private

# File lib/poise_derived/lazy_attribute.rb, line 99
def ==(other)
  _evaluate == other
end
_override(str) click to toggle source

Return a copy of this attribute with the same node context but an override value as the format string. This can't support blocks because of how it is called generally.

@api private @see PoiseDerived::CoreExt @return [PoiseDerived::LazyAttribute]

# File lib/poise_derived/lazy_attribute.rb, line 57
def _override(str)
  self.class.new(@node, str)
end
inspect() click to toggle source

Shorter inspect output for debugging so we don't vomit the node into the log or spec output.

@return [String]

# File lib/poise_derived/lazy_attribute.rb, line 42
def inspect
  if @value.is_a?(Proc)
    "#<#{self.class.name} @value=proc>"
  else
    "#<#{self.class.name} @value=#{@value.inspect}>"
  end
end
is_a?(klass) click to toggle source

Fake is_a? and kind_of? for params_validate and `_pv_kind_of`. @api private

# File lib/poise_derived/lazy_attribute.rb, line 88
def is_a?(klass)
  return true if Object.instance_method(:is_a?).bind(self).call(klass)
  klass <= String
end
Also aliased as: kind_of?
kind_of?(klass)

@api private @see is_a?

Alias for: is_a?
method_missing(method, *args, &block) click to toggle source

@!group delegators Delegate to the lazy value. @api private

# File lib/poise_derived/lazy_attribute.rb, line 64
def method_missing(method, *args, &block)
  _evaluate.send(method, *args, &block)
end
respond_to_missing?(method, include_all) click to toggle source

Delegate to the lazy value. @api private

# File lib/poise_derived/lazy_attribute.rb, line 70
def respond_to_missing?(method, include_all)
  _evaluate.respond_to?(method, include_all)
end
to_s() click to toggle source

Delegate to the lazy value. @api private

# File lib/poise_derived/lazy_attribute.rb, line 76
def to_s
  _evaluate.to_s
end
to_str() click to toggle source

Make sure we implement to_str because that activates the == hack. @api private

# File lib/poise_derived/lazy_attribute.rb, line 82
def to_str
  to_s
end

Private Instance Methods

_evaluate() click to toggle source

Evaluate the lazy attribute.

@return [Object]

# File lib/poise_derived/lazy_attribute.rb, line 109
def _evaluate
  return @evaluate_cache if defined?(@evaluate_cache)
  @evaluate_cache = if @value.is_a?(Proc)
    # Block mode, just run the block.
    @node.instance_eval(&@value).to_s
  else
    # String mode, parse the template string and fill it in.
    format_keys = @value.scan(FORMAT_STRING_REGEXP).inject({}) do |memo, (key)|
      # Keys must be symbols because Ruby.
      memo[key.to_sym] = key.split(/\./).inject(@node) {|n, k| n.nil? ? n : n[k] }
      memo
    end
    @value % format_keys
  end
end