2013-02-13 48 views
2

我是一个Ruby新手,但我试图渲染Puppet .erb模板使用脚本和负载的合成数据(我会放入Yaml文件或其他东西)。我们的木偶模板大多是沿着这些各种各样的行:来自哈希的红宝石.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

事实证明,这简直太惊人了!我发现你可以使用特殊的方法“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) 

此代码仍然不会处理模板像<% = @variable%>,但它会处理我原来的问题中的另外两种情况。