Class: ConfigManager::DefaultInterpolator

Inherits:
Object
  • Object
show all
Defined in:
lib/configmanager/interpolators.rb

Overview

The default interpolator that will look for ${} property references. The interpolator will only inspect Strings and Strings in Arrays. All other types are returned as is.

Constant Summary collapse

REFERENCE_REGEX =
/\$\{[\w\.]+\}/

Class Method Summary collapse

Class Method Details

.interpolate(key, raw_value, context, options = {}) ⇒ String

Replaces all ${} references with an actual value. Will evaluate any nested references too. If circular references are detected, an exception is raised.

Parameters:

  • key (String)

    the full (. separated) key against which this value was stored.

  • raw_value (String, Array)

    the raw value to interpolate.

  • context (ConfigManager::Configuration)

    the context under which the value should be evaluated.

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

    extra configuration options. Supported keys are: :replacements - a hash containing replacement values for references. References are replaced with these value on priority. :tolerate_missing_properties - a flag to indicate if an exception should be raised if referenced properties are missing.

Returns:

  • (String)

    the fully interpolated value.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/configmanager/interpolators.rb', line 27

def self.interpolate(key, raw_value, context, options = {})
  # Default options.
  replacements = get_option(options, :replacements, false, {})
  tolerate_missing_references = get_option(options, :tolerate_missing_references, false, false)
  interpolating = set_option(options, :interpolating, {}, false)
  # Mark this key
  interpolating[key] = true
  # Check for type.
  # Array - Recursively call this method.
  # Not a String - Return as is.
  # Otherwise, interpolate!
  return raw_value.map { |item| interpolate(key, item, context, options) } if raw_value.kind_of?(Array)
  return raw_value unless raw_value.kind_of?(String)
  raw_value.gsub(REFERENCE_REGEX) do |reference|
    # If the referenced key is still being interpolated, its a circular reference!
    # Otherwise, substitute it with its replacement value (either from the supplied hash, or the provided context)
    key = reference[2..-2]
    if interpolating[key]
      trace = (interpolating.keys + [key]).join(" -> ")
      raise ConfigManager::CircularReferenceError.new("Cannot interpolate - Circular reference detected. Trace: #{trace}")
    elsif replacements.has_key?(key)
      replacements[key]
    elsif context.has_property?(key)
      context.get_property(key, options)
    elsif tolerate_missing_references
      reference
    else
      trace = (interpolating.keys + [key]).join(" -> ")
      raise ConfigManager::PropertyNotFoundError.new("Cannot interpolate - Referenced key '#{key}' does not exist. Trace: #{trace}")
    end
  end
ensure
  # Done, so mark as done.
  interpolating.delete(key)
end