La solution la plus Simple, l'utilisation OpenStruct:
require 'erb'
require 'ostruct'
namespace = OpenStruct.new(name: 'Joan', last: 'Maragall')
template = 'Name: <%= name %> <%= last %>'
puts ERB.new(template).result(namespace.instance_eval { binding })
#=> Name: Joan Maragall
Le code ci-dessus est assez simple, mais a (au moins) deux problèmes: 1), Car elle s'appuie sur OpenStruct
, un accès à un non-existant des rendements variables en nil
tandis que vous préfèrerez sûrement qu'il n'a pas bruyamment. 2) binding
est appelée à l'intérieur d'un bloc, c'est en la fermeture, de sorte qu'il inclut toutes les variables locales dans le champ d'application (en fait, ils se font de l'ombre aux attributs de la structure!).
Voici donc une autre solution, plus détaillé, mais sans aucun de ces problèmes:
class Namespace
def initialize(hash)
hash.each do |key, value|
singleton_class.send(:define_method, key) { value }
end
end
def get_binding
binding
end
end
template = 'Name: <%= name %> <%= last %>'
ns = Namespace.new(name: 'Joan', last: 'Maragall')
ERB.new(template).result(ns.get_binding)
#=> Name: Joan Maragall
Bien sûr, si vous allez utiliser souvent, assurez-vous de créer un String#erb
extension qui vous permet de vous écrire quelque chose comme "x=<%= x %>, y=<%= y %>".erb(x: 1, y: 2)
.