2013-02-13 20 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%>,但它會處理我原來的問題中的另外兩種情況。