我正在Ruby项目中实现HTML模板(非rails)。要做到这一点,我将使用ERB,但我对绑定的东西有一些担忧。
首先,这是我到目前为止的方法:
def self.template(template, data)
template = File.read("#{ENV.root}/app/templates/#{template}.html.erb")
template_binding = binding.clone
data.each do |k, v|
template_binding.local_variable_set(k, v)
end
ERB.new(template).result(template_binding)
end
要打电话给我,我只会做
Email.template('email/hello', {
name: 'Bill',
age: 41
}
目前的解决方案存在两个问题。
首先,我正在克隆当前的绑定。我想创建一个新的。我尝试Class.new.binding
创建一个新的,但由于binding
是一个私有方法,因此无法以这种方式获取。
我想要一个新的原因是我想避免实例变量泄漏到ERB文件或从ERB文件泄漏的风险(克隆只处理后一种情况)。
第二,我希望传递给ERB文件的变量作为实例变量公开。在这里,我尝试使用template_binding.instance_variable_set
,传递普通哈希键k
,它抱怨它不是一个有效的实例变量名称和"@#{k}"
,它没有抱怨但也没有提供在ERB代码中。
我想要使用实例变量的原因是,依赖于此代码的人员熟悉这种惯例。
我已在Stack Overflow上查看了一些主题,例如Render an ERB template with values from a hash,但所提供的答案并未解决我正在讨论的问题。
简而言之,就像标题一样:如何创建新的绑定并为ERB中的可用性分配实例变量?
答案 0 :(得分:2)
1)无需克隆,每次都为您创建新的绑定。
我在irb中测试了这个:
class A; def bind; binding; end; end
a = A.new
bind_1 = a.bind
bind_2 = a.bind
bind_1.local_variable_set(:x, 2)
=> 2
bind_1.local_variables
=> [:x]
bind_2.local_variables
=> []
2)打开对象Eigenclass并向其添加attr_accessor
class << template_binding # this opens Eigenclass for object template_binding
attr_accessor :x
end
所以在ruby中你可以打开任何类并为它添加方法。 Eigenclass表示单个对象的类 - 每个对象都可以具有自定义类定义。来自C#,我无法想象这种情况会被使用,直到现在。 :)
为每个哈希
执行此操作data.each do |k, v|
class << template_binding; attr_accessor k.to_sym; end
template_binding.k = v
end