如何创建新的绑定并为其分配实例变量以在 ERB 中可用?
How to create new binding and assign instance variables to it for availability in ERB?
我正在 Ruby 项目 (non-rails) 中实施 HTML 模板。为此,我将使用 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文件的变量暴露为实例变量。在这里,我尝试使用 template_binding.instance_variable_set
,传递普通散列键 k
,它抱怨它不是一个有效的实例变量名称和 "@#{k}"
,它没有抱怨但也没有可用在 ERB 代码中。
我想使用实例变量的原因是依赖此代码的人熟悉它。
我在 Stack Overflow 上查看了一些主题,例如 Render an ERB template with values from a hash,但提供的答案并未解决我正在讨论的问题。
简而言之,就像标题一样:如何创建新的绑定并为其分配实例变量以便在 ERB 中可用?
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 中,您可以打开任何 class 并为其添加方法。
Eigenclass 表示单个对象的 class - 每个对象都可以有自定义的 class 定义。来自 C#,直到现在我无法想象会使用它的情况。 :)
对每个哈希执行此操作
data.each do |k, v|
class << template_binding; attr_accessor k.to_sym; end
template_binding.k = v
end
我正在 Ruby 项目 (non-rails) 中实施 HTML 模板。为此,我将使用 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文件的变量暴露为实例变量。在这里,我尝试使用 template_binding.instance_variable_set
,传递普通散列键 k
,它抱怨它不是一个有效的实例变量名称和 "@#{k}"
,它没有抱怨但也没有可用在 ERB 代码中。
我想使用实例变量的原因是依赖此代码的人熟悉它。
我在 Stack Overflow 上查看了一些主题,例如 Render an ERB template with values from a hash,但提供的答案并未解决我正在讨论的问题。
简而言之,就像标题一样:如何创建新的绑定并为其分配实例变量以便在 ERB 中可用?
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 中,您可以打开任何 class 并为其添加方法。 Eigenclass 表示单个对象的 class - 每个对象都可以有自定义的 class 定义。来自 C#,直到现在我无法想象会使用它的情况。 :)
对每个哈希执行此操作
data.each do |k, v|
class << template_binding; attr_accessor k.to_sym; end
template_binding.k = v
end