Je dois ignorer quelque chose de très simple ici, mais je n'arrive pas à comprendre comment rendre un modèle ERB simple avec des valeurs d'une table de hachage.
Je suis relativement nouveau pour Ruby, venant de python. J'ai un modèle ERB (pas HTML), dont j'ai besoin rendu avec le contexte qui doit être pris à partir d'une carte de hachage, que je reçois d'une source externe.
Cependant, la documentation d'ERB indique que la méthode ERB.result
Prend un binding
. J'ai appris qu'ils contiennent des contextes variables dans Ruby (quelque chose comme locals()
et globals()
en python, je suppose?). Mais, Je ne sais pas comment créer un objet de liaison à partir de ma carte de hachage.
Un peu (un beaucoup , en fait) googler m'a donné ceci: http://refactormycode.com/codes/281-given-a -hash-of-variables-render-an-erb-template , qui utilise une magie de métaprogrammation Ruby qui m'échappe).
Alors, n'y a-t-il pas une solution simple à ce problème? Ou existe-t-il un meilleur moteur de modélisation (non lié au HTML) mieux adapté à cela? (J'ai seulement choisi ERB parce que c'est dans le stdlib).
Je ne sais pas si cela peut être qualifié de "plus élégant" ou non:
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 %>')
Ou à partir d'une méthode de classe:
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 a Erb, T pour modèle et sonne comme "tisane". Nommer les choses est difficile.)
require 'erb'
require 'ostruct'
def erb(template, vars)
ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
end
par exemple
1.9.2p290 :008 > erb("Hey, <%= first_name %> <%= last_name %>", :first_name => "James", :last_name => "Moriarty")
=> "Hey, James Moriarty"
Si vous pouvez utiliser Erubis vous avez déjà cette fonctionnalité:
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"
Ruby 2.5 a ERB#result_with_hash
qui fournit cette fonctionnalité:
$ Ruby -rerb -e 'p ERB.new("Hi <%= name %>").result_with_hash(name: "Tom")'
"Hi Tom"
La partie délicate ici n'est pas de polluer la liaison avec des variables locales redondantes (comme dans les réponses les mieux notées):
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)
Solution simple utilisant Binding :
b = binding
b.local_variable_set(:a, 'a')
b.local_variable_set(:b, 'b')
ERB.new(template).result(b)
Si vous voulez faire les choses très simplement, vous pouvez toujours utiliser des recherches de hachage explicites dans le modèle ERB. Imaginons que vous utilisiez "binding" pour passer une variable de hachage appelée "hash" dans le modèle, cela ressemblerait à ceci:
<%= hash["key"] %>