如何创建新绑定并为其分配实例变量以获得ERB中的可用性?

时间:2017-01-11 11:40:57

标签: ruby erb

我正在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中的可用性分配实例变量?

1 个答案:

答案 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