ruby 使用哈希值呈现 ERB 模板
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8954706/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Render an ERB template with values from a hash
提问by Shrikant Sharat
I must be overlooking something very simple here but I can't seem to figure out how to render a simple ERB template with values from a hash-map.
我一定在这里忽略了一些非常简单的东西,但我似乎无法弄清楚如何使用哈希映射中的值呈现一个简单的 ERB 模板。
I am relatively new to ruby, coming from python. I have an ERB template (not HTML), which I need rendered with context that's to be taken from a hash-map, which I receive from an external source.
我对 ruby 比较陌生,来自 python。我有一个 ERB 模板(不是 HTML),我需要使用从外部源接收的哈希映射中获取的上下文来呈现它。
However, the documentation of ERB, states that the ERB.resultmethod takes a binding. I learnt that they are something that hold the variable contexts in ruby (something like locals()and globals()in python, I presume?). But, I don't know how I can build a binding object out of my hash-map.
但是,ERB 的文档指出该ERB.result方法采用binding. 我才知道,他们是保持着可变背景的红宝石东西(像locals()和globals()在python,我相信?)。但是,我不知道如何从哈希映射中构建绑定对象。
A little (a lot, actually) googling gave me this: http://refactormycode.com/codes/281-given-a-hash-of-variables-render-an-erb-template, which uses some ruby metaprogramming magic that escapes me.
一点点(实际上很多)谷歌搜索给了我这个:http: //refactormycode.com/codes/281-given-a-hash-of-variables-render-an-erb-template,它使用了一些 ruby 元编程魔法逃脱我。
So, isn't there a simple solution to this problem? Or is there a better templating engine (not tied to HTML) better suited for this? (I only chose ERB because its in the stdlib).
那么,这个问题难道没有简单的解决方案吗?或者是否有更好的模板引擎(不绑定到 HTML)更适合于此?(我只选择 ERB 因为它在 stdlib 中)。
采纳答案by Dave Newton
I don't know if this qualifies as "more elegant" or not:
我不知道这是否符合“更优雅”的条件:
require 'erb'
require 'ostruct'
class ErbalT < OpenStruct
def render(template)
ERB.new(template).result(binding)
end
end
et = ErbalT.new({ :first => 'Mislav', 'last' => 'Marohnic' })
puts et.render('Name: <%= first %> <%= last %>')
Or from a class method:
或者从一个类方法:
class ErbalT < OpenStruct
def self.render_from_hash(t, h)
ErbalT.new(h).render(t)
end
def render(template)
ERB.new(template).result(binding)
end
end
template = 'Name: <%= first %> <%= last %>'
vars = { :first => 'Mislav', 'last' => 'Marohnic' }
puts ErbalT::render_from_hash(template, vars)
(ErbalT has Erb, T for template, and sounds like "herbal tea". Naming things is hard.)
(ErbalT 有 Erb,T 表示模板,听起来像“凉茶”。命名很难。)
回答by Moriarty
require 'erb'
require 'ostruct'
def render(template, vars)
ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
end
e.g
例如
render("Hey, <%= first_name %> <%= last_name %>", first_name: "James", last_name: "Moriarty")
# => "Hey, James Moriarty"
Update:
更新:
A simple example without ERB:
一个没有 ERB 的简单例子:
def render(template, vars)
eval template, OpenStruct.new(vars).instance_eval { binding }
end
e.g.
例如
render '"Hey, #{first_name} #{last_name}"', first_name: "James", last_name: "Moriarty"
# => "Hey, James Moriarty
Update 2: checkout @adam-spiers comment below.
更新 2:在下面结帐@adam-spiers 评论。
回答by Phrogz
If you can use Erubisyou have this functionality already:
如果您可以使用Erubis,则您已经拥有此功能:
irb(main):001:0> require 'erubis'
#=> true
irb(main):002:0> locals = { first:'Gavin', last:'Kistner' }
#=> {:first=>"Gavin", :last=>"Kistner"}
irb(main):003:0> Erubis::Eruby.new("I am <%=first%> <%=last%>").result(locals)
#=> "I am Gavin Kistner"
回答by Tom Copeland
Ruby 2.5 has ERB#result_with_hashwhich provides this functionality:
Ruby 2.5ERB#result_with_hash提供了以下功能:
$ ruby -rerb -e 'p ERB.new("Hi <%= name %>").result_with_hash(name: "Tom")'
"Hi Tom"
回答by Lev Lukomsky
The tricky part here is not to pollute binding with redundant local variables (like in top-rated answers):
这里的棘手部分是不要用冗余局部变量来污染绑定(例如在最高评价的答案中):
require 'erb'
class TemplateRenderer
def self.empty_binding
binding
end
def self.render(template_content, locals = {})
b = empty_binding
locals.each { |k, v| b.local_variable_set(k, v) }
# puts b.local_variable_defined?(:template_content) #=> false
ERB.new(template_content).result(b)
end
end
# use it
TemplateRenderer.render('<%= x %> <%= y %>', x: 1, y: 2) #=> "1 2"
# use it 2: read template from file
TemplateRenderer.render(File.read('my_template.erb'), x: 1, y: 2)
回答by asfer
回答by Alex D
If you want to do things very simply, you can always just use explicit hash lookups inside the ERB template. Say you use "binding" to pass a hash variable called "hash" into the template, it would look like this:
如果您想非常简单地做事,您总是可以在 ERB 模板中使用显式哈希查找。假设您使用“binding”将一个名为“hash”的哈希变量传递到模板中,它看起来像这样:
<%= hash["key"] %>

