Визуализация шаблона ERB со значениями из хеша - PullRequest
56 голосов
/ 21 января 2012

Я, должно быть, пропускаю что-то очень простое здесь, но я не могу понять, как отобразить простой шаблон ERB со значениями из хэш-карты.

Я относительно новичок в ruby, пришедший изпитон.У меня есть шаблон ERB (не HTML), который мне нужно визуализировать с контекстом, который нужно взять из хеш-карты, которую я получаю из внешнего источника.

Однако в документации ERB говорится, чтоERB.result метод занимает binding.Я узнал, что они содержат переменные контексты в ruby ​​(я полагаю, что-то вроде locals() и globals() в python?).Но я не знаю, как я могу построить привязывающий объект из моей хеш-карты.

Небольшое ( лот , на самом деле) поиск в Google дал мне это: http://refactormycode.com/codes/281-given-a-hash-of-variables-render-an-erb-template,, которая использует магию рубинового метапрограммирования, которая ускользает от меня.

Итак, нет ли простого решения этой проблемы?Или для этого лучше подходит шаблонизатор (не привязанный к HTML)?(Я выбрал только ERB, потому что он в stdlib).

Ответы [ 7 ]

74 голосов
/ 16 марта 2012
require 'erb'
require 'ostruct'

def erb(template, vars)
  ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
end

* 1002 например *

1.9.2p290 :008 > erb("Hey, <%= first_name %> <%= last_name %>", :first_name => "James", :last_name => "Moriarty")
 => "Hey, James Moriarty" 
56 голосов
/ 21 января 2012

Я не знаю, квалифицируется ли это как «более элегантный» или нет:

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 для шаблона и звучит как «травяной чай». Назвать вещи сложно.)

32 голосов
/ 21 января 2012

Если вы можете использовать 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"
24 голосов
/ 30 мая 2017

Ruby 2.5 имеет ERB#result_with_hash, который обеспечивает эту функциональность:

$ ruby -rerb -e 'p ERB.new("Hi <%= name %>").result_with_hash(name: "Tom")'
"Hi Tom"
8 голосов
/ 15 июня 2016

Сложная задача - не загрязнять привязку избыточными локальными переменными (как в самых популярных ответах):

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 голосов
/ 18 января 2015

Простое решение с использованием Связывание :

b = binding
b.local_variable_set(:a, 'a')
b.local_variable_set(:b, 'b')
ERB.new(template).result(b)
4 голосов
/ 21 января 2012

Если вы хотите сделать что-то очень просто, вы всегда можете просто использовать явный поиск хеша внутри шаблона ERB.Допустим, вы используете «связывание» для передачи хеш-переменной с именем «хеш» в шаблон, это будет выглядеть так:

<%= hash["key"] %>
...