来自哈希的Ruby .erb模板,但是捕获未设置的变量

时间:2013-02-13 10:35:49

标签: ruby erb

我是一个Ruby-newbie,但我正在尝试使用脚本和一堆合成数据(我将放入Yaml文件或其他东西)来渲染Puppet .erb模板。我们的木偶模板主要是这些行:

# Some config file
<%= @some_ordinary_variable %>
<%= some_other_variable %>
<%= @something_undefined %>
<%= scope.function_hiera("some_hiera_variable") %>

我已经嘲笑了hiera查找,并发现Problem using OpenStruct with ERB作为替换“some_other_variable”的一种方式(我有点坚持让“@some_ordinary_variable”工作,但是我想我可以想出那个。

我要问的是如何使用一个绑定来让我在每个变量查找中运行一些代码?我想我想运行类似的东西:

def variable_lookup(key)
  if @variables.has_key?(key)
    return @variables[key]
  else
    warn "The variable " + key + " is required by the template but not set"
  end
end

然后我可以将其与我的Hiera模型合并以查找Hiera数据。我到目前为止的代码是:

require 'rubygems'
require 'yaml'
require 'erb'
require 'ostruct'

class ErbBinding < OpenStruct
  include Enumerable
  attr_accessor :yamlfile, :hiera_config, :erbfile, :yaml

  def scope
    self
  end

  def function_hiera(key)
    val = @yaml['values'][key]
    if val.is_a?(YAML::Syck::Scalar)
      return val.value
    else
      warn "erby: " + key + " required in template but not set in yaml"
      return nil
    end
  end

  def get_binding
    return binding()
  end
end

variables = {'some_other_variable' => 'hello world'}

hs = ErbBinding.new(variables)
template = File.read('./template.erb')
hs.yaml = YAML.parse( File.read('./data.yaml') )

erb = ERB.new(template)

vars_binding = hs.send(:get_binding)
puts erb.result(vars_binding)

我无法弄清楚如何设置运行代码的绑定,而不仅仅是使用'变量'哈希。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

事实证明这非常简单!我发现你可以使用特殊方法“method_missing”来挖掘未定义的所有方法调用。也就是说,我们使用绑定将哈希变成对象(每个哈希键成为对象中的方法)。如果有一个缺少的方法(即哈希中没有键设置),那么Ruby调用“method_missing” - 我所做的只是说明了缺少的方法名称。如果在此处找到了重要的信息:http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html

如果你想知道,这是我到目前为止的总代码......

require 'rubygems'
require 'yaml'
require 'erb'
require 'ostruct'

class ErbBinding < OpenStruct
  include Enumerable
  attr_accessor :yamlfile, :hiera_config, :erbfile, :yaml

  def method_missing(m, *args, &block)
    warn "erby: Variable #{m} required but not set in yaml"
  end

  def scope
    self
  end

  def function_hiera(key)
    val = @yaml['values'][key]
    if val.is_a?(YAML::Syck::Scalar)
      return val.value
    else
      warn "erby: " + key + " required in template but not set in yaml"
      return nil
    end
  end

  def get_binding
    return binding()
  end
end

variables = {'some_other_variable' => 'hello world'}

hs = ErbBinding.new(variables)
template = File.read('./template.erb')
hs.yaml = YAML.parse( File.read('./data.yaml') )

erb = ERB.new(template)

vars_binding = hs.send(:get_binding)
puts erb.result(vars_binding)

此代码仍然无法处理类似&lt;%= @variable%&gt;的模板,但它会处理原始问题中的其他两种情况。