Program Tip

해시의 값으로 ERB 템플릿 렌더링

programtip 2020. 12. 13. 10:26
반응형

해시의 값으로 ERB 템플릿 렌더링


여기서 매우 간단한 것을 간과해야하지만 해시 맵의 값으로 간단한 ERB 템플릿을 렌더링하는 방법을 알아낼 수없는 것 같습니다.

나는 파이썬에서 온 루비에 비교적 익숙하지 않습니다. ERB 템플릿 (HTML이 아님)이 있는데, 외부 소스에서받은 해시 맵에서 가져온 컨텍스트로 렌더링해야합니다.

그러나 ERB 문서에는 ERB.result메서드가 binding. 나는 그들이 루비에서 변수 컨텍스트를 잡고 뭔가 것을 배웠다 (같은 locals()globals()파이썬에서, 나는 가정?). 하지만 내 해시 맵에서 바인딩 개체를 만드는 방법을 모르겠습니다.

약간의 ( 실제로 많은 ) 인터넷 검색을 통해 http://refactormycode.com/codes/281-given-a-hash-of-variables-render-an-erb-template , 일부 루비 메타 프로그래밍 마법을 사용합니다. 나를 탈출합니다.

그렇다면이 문제에 대한 간단한 해결책이 없습니까? 아니면 이것에 더 적합한 더 나은 템플릿 엔진 (HTML에 묶이지 않음)이 있습니까? (나는 stdlib에 있기 때문에 ERB 만 선택했습니다).


이것이 "더 우아함"인지 아닌지 모르겠습니다.

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가 있으며 "허벌티"처럼 들립니다. 이름을 지정하는 것은 어렵습니다.)


require 'erb'
require 'ostruct'

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

예 :

render("Hey, <%= first_name %> <%= last_name %>", first_name: "James", last_name: "Moriarty")
# => "Hey, James Moriarty" 

최신 정보:

ERB가없는 간단한 예 :

def render(template, vars)
  eval template, OpenStruct.new(vars).instance_eval { binding }
end

예 :

render '"Hey, #{first_name} #{last_name}"', first_name: "James", last_name: "Moriarty"
# => "Hey, James Moriarty

업데이트 2 : 아래 @ adam-spiers 댓글을 확인하세요.


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"

Ruby 2.5 has ERB#result_with_hash which provides this functionality:

$ ruby -rerb -e 'p ERB.new("Hi <%= name %>").result_with_hash(name: "Tom")'
"Hi Tom"

The tricky part here is not to pollute binding with redundant local variables (like in top-rated answers):

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)

Simple solution using Binding:

b = binding
b.local_variable_set(:a, 'a')
b.local_variable_set(:b, 'b')
ERB.new(template).result(b)

If you want to do things very simply, you can always just use explicit hash lookups inside the ERB template. Say you use "binding" to pass a hash variable called "hash" into the template, it would look like this:

<%= hash["key"] %>

참고URL : https://stackoverflow.com/questions/8954706/render-an-erb-template-with-values-from-a-hash

반응형