Отобразить шаблон ERB со значениями из хэша
Мне нужно пропустить что-то очень простое здесь, но я не могу понять, как сделать простой шаблон ERB со значениями из хэш-карты.
Я относительно новичок в ruby, исходящий из python. У меня есть шаблон ERB (а не HTML), который мне нужно отобразить с помощью контекста, который нужно взять с хэш-карты, которую я получаю от внешнего источника.
Однако в документации ERB указано, что метод ERB.result
принимает binding
. Я узнал, что они представляют собой переменные контекста в ruby (что-то вроде locals()
и globals()
в python, я полагаю?). Но я не знаю, как я могу построить объект привязки из своей хэш-карты.
Немного (много, на самом деле) googling дал мне это: http://refactormycode.com/codes/281-given-a-hash-of-variables-render-an-erb-template, в котором используется магия метапрограммирования ruby, которая ускользает от меня.
Итак, разве нет простого решения этой проблемы? Или есть лучший механизм шаблонов (не привязанный к HTML), который лучше подходит для этого? (Я выбрал только ERB, потому что его в stdlib).
Ответы
Ответ 1
Я не знаю, соответствует ли это "более элегантным" или нет:
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 %>')
Или из метода класса:
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 имеет Erb, T для шаблона и звучит как "травяной чай". Именование вещей сложно.)
Ответ 2
require 'erb'
require 'ostruct'
def erb(template, vars)
ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
end
например
1.9.2p290 :008 > erb("Hey, <%= first_name %> <%= last_name %>", :first_name => "James", :last_name => "Moriarty")
=> "Hey, James Moriarty"
Ответ 3
Если вы можете использовать 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"
Ответ 4
Простое решение с использованием Binding:
b = binding
b.local_variable_set(:a, 'a')
b.local_variable_set(:b, 'b')
ERB.new(template).result(b)
Ответ 5
Трудная часть здесь заключается в том, чтобы не загрязнять привязку с избыточными локальными переменными (например, в наиболее популярных ответах):
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)
Ответ 6
Если вы хотите сделать что-то очень просто, вы всегда можете просто использовать явные хэш-запросы внутри шаблона ERB. Предположим, вы используете "привязку" для передачи хеш-переменной, называемой "хэш" в шаблон, она будет выглядеть так:
<%= hash["key"] %>
Ответ 7
Ruby 2.5 имеет ERB#result_with_hash
, который обеспечивает эту функциональность:
$ ruby -rerb -e 'p ERB.new("Hi <%= name %>").result_with_hash(name: "Tom")'
"Hi Tom"