code - erb ruby html
Renderiza una plantilla ERB con valores de un hash (7)
Debo estar pasando por alto algo muy simple aquí, pero parece que no consigo encontrar una plantilla ERB simple con valores de un hash-map.
Soy relativamente nuevo en el rubí, viniendo de python. Tengo una plantilla ERB (no HTML), que necesito renderizar con el contexto que se debe tomar de un hash-map, que recibo de una fuente externa.
Sin embargo, la documentación de ERB, establece que el método ERB.result
toma un binding
. Aprendí que son algo que mantiene los contextos variables en ruby (algo así como locals()
y globals()
en python, supongo?). Pero, no sé cómo puedo construir un objeto de enlace de mi hash-map.
Un poco ( mucho , en realidad) de Google me dio esto: http://refactormycode.com/codes/281-given-a-hash-of-variables-render-an-erb-template , que usa algo de magia de metaprogramación rubí que se me escapa
Entonces, ¿no hay una solución simple para este problema? ¿O hay un motor de plantillas mejor (no vinculado a HTML) más adecuado para esto? (Solo elegí ERB porque está en el stdlib).
La parte difícil aquí no es contaminar el enlace con variables locales redundantes (como en las respuestas más valoradas):
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)
No sé si esto califica como "más elegante" o no:
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 %>'')
O a partir de un método de clase:
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 tiene Erb, T para la plantilla y suena como "té de hierbas". Nombrar cosas es difícil).
Ruby 2.5 tiene ERB#result_with_hash
que proporciona esta funcionalidad:
$ ruby -rerb -e ''p ERB.new("Hi <%= name %>").result_with_hash(name: "Tom")''
"Hi Tom"
Si desea hacer las cosas de manera muy simple, siempre puede usar búsquedas de hash explícitas dentro de la plantilla ERB. Digamos que usa "enlace" para pasar una variable de hash llamada "hash" a la plantilla, se vería así:
<%= hash["key"] %>
Si puedes usar Erubis ya tienes esta funcionalidad:
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"
Solución simple utilizando Binding :
b = binding
b.local_variable_set(:a, ''a'')
b.local_variable_set(:b, ''b'')
ERB.new(template).result(b)
require ''erb''
require ''ostruct''
def erb(template, vars)
ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
end
p.ej
1.9.2p290 :008 > erb("Hey, <%= first_name %> <%= last_name %>", :first_name => "James", :last_name => "Moriarty")
=> "Hey, James Moriarty"