ERB – Ruby 템플릿

ERB – Ruby 템플릿

소개

ERB는 Ruby를 위한 쓰기 쉽지만 강력한 템플릿 시스템을 제공해요. ERB를 쓰면 어떤 일반 텍스트 문서에도 실제 Ruby 코드를 넣어서 문서 정보를 생성하거나 흐름 제어를 할 수 있어요.

아주 간단한 예시예요:

require 'erb'

x = 42
template = ERB.new <<-EOF
  The value of x is: <%= x %>
EOF
puts template.result(binding)

출력: The value of x is: 42

더 복잡한 예시는 아래에 있어요.

출처: Ruby 3.3 API

본문

인식되는 태그

ERB는 주어진 템플릿에서 특정 태그를 인식하고 아래 규칙에 따라 변환해요.

<% Ruby code -- inline with output %>
<%= Ruby expression -- replace with result %>
<%# comment -- ignored -- useful in testing %> (`<% #` doesn't work. Don't use Ruby comments.)
% a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
%% replaced with % if first thing on a line and % processing is used
<%% or %%> -- replace with <% or %> respectively

그 외의 모든 텍스트는 ERB 필터링을 거쳐 그대로 전달돼요.

옵션

ERB를 쓸 때 바꿀 수 있는 설정이 몇 가지 있어요.

  • 인식되는 태그의 성격.
  • 템플릿에서 지역 변수를 해석하는 데 쓰이는 바인딩.

자세한 내용은 ERB.newERB#result 메서드를 보세요.

문자 인코딩

ERB(또는 ERB가 생성한 Ruby 코드)는 입력 문자열과 같은 문자 인코딩의 문자열을 돌려줘요. 다만 입력 문자열에 매직 코멘트가 있으면, 매직 코멘트가 지정한 인코딩의 문자열을 돌려줘요.

# -*- coding: utf-8 -*-
require 'erb'

template = ERB.new <<EOF
<%#-*- coding: Big5 -*-%>
 \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
EOF
puts template.result

출력: _ENCODING_ is Big5.

예시

일반 텍스트

ERB는 어떤 일반적인 템플릿 상황에도 유용해요. 이 예시에서는 편리한 "줄 시작의 %" 태그를 쓰고, 백슬래시 문제를 피하려고 %q{...}로 템플릿을 글자 그대로 인용해요.

require "erb"

# 템플릿 만들기.
template = %q{
  From: James Edward Gray II <[email protected]>
  To: <%= to %>
  Subject: Addressing Needs

  <%= to[/\w+/] %>:

  Just wanted to send a quick note assuring that your needs are being
  addressed.

  I want you to know that my team will keep working on the issues,
  especially:

  <%# ignore numerous minor requests -- focus on priorities %>
  % priorities.each do |priority|
  * <%= priority %>
  % end

  Thanks for your patience.

  James Edward Gray II
}.gsub(/^ /, '')

message = ERB.new(template, trim_mode: "%<>")

# 템플릿 데이터 설정.
to = "Community Spokesman <spokesman@ruby_community.org>"
priorities = [ "Run Ruby Quiz",
               "Document Modules",
               "Answer Questions on Ruby Talk" ]

# 결과 생성.
email = message.result
puts email

HTML 속의 Ruby

ERB.rhtml 파일(HTML 안에 Ruby가 들어 있는)에서 자주 쓰여요. 이 예시에서 템플릿 실행 시 특별한 바인딩을 제공해서 Product 객체의 인스턴스 변수를 해석할 수 있게 해야 한다는 점에 주목하세요.

require "erb"

# 템플릿 데이터 클래스 만들기.
class Product
  def initialize( code, name, desc, cost )
    @code = code
    @name = name
    @desc = desc
    @cost = cost

    @features = [ ]
  end

  def add_feature( feature )
    @features << feature
  end

  # 멤버 데이터 템플릿 지원.
  def get_binding
    binding
  end

  # ...
end

# 템플릿 만들기.
template = %{
  <html>
  <head><title>Ruby Toys -- <%= @name %></title></head>
  <body>

  <h1><%= @name %> (<%= @code %>)</h1>
  <p><%= @desc %></p>

  <ul>
  <% @features.each do |f| %>
  <li><b><%= f %></b></li>
  <% end %>
  </ul>

  <p>
  <% if @cost < 10 %>
  <b>Only <%= @cost %>!!!</b>
  <% else %>
  Call for a price, today!
  <% end %>
  </p>

  </body>
  </html>
}.gsub(/^ /, '')

rhtml = ERB.new(template)

# 템플릿 데이터 설정.
toy = Product.new( "TZ-1002",
                   "Rubysapien",
                   "Geek's Best Friend! Responds to Ruby commands...",
                   999.95 )
toy.add_feature("Listens for verbal commands in the Ruby language!")
toy.add_feature("Ignores Perl, Java, and all C variants.")
toy.add_feature("Karate-Chop Action!!!")
toy.add_feature("Matz signature on left leg.")
toy.add_feature("Gem studded eyes... Rubies, of course!")

# 결과 생성.
rhtml.run(toy.get_binding)

참고

다양한 Ruby 프로젝트에서 여러 템플릿 솔루션을 쓸 수 있어요. 예를 들어 Ruby와 함께 배포되는 RDoc은 자체 템플릿 엔진을 쓰는데, 그것을 다른 곳에서 재사용할 수도 있어요. 다른 인기 있는 엔진들은 The Ruby Toolbox의 해당 카테고리에서 찾을 수 있어요.

상수

  • NOT_GIVEN
  • VERSION

속성

  • encoding[R] — eval에 쓰일 인코딩.
  • filename[RW]ERB 코드가 실행될 때 Kernel#eval에 전달되는 선택적 filename 인자.
  • lineno[RW]ERB 코드가 실행될 때 Kernel#eval에 전달되는 선택적 lineno 인자.
  • src[R]ERB가 생성한 Ruby 코드.

클래스 메서드

  • new(str, safe_level=NOT_GIVEN, legacy_trim_mode=NOT_GIVEN, legacy_eoutvar=NOT_GIVEN, trim_mode: nil, eoutvar: '_erbout') — str에 지정된 템플릿으로 새 ERB 객체를 만들어요. ERB 객체는 실행하면 완성된 템플릿을 출력하는 Ruby 코드를 만들어 내는 방식으로 동작해요.

trim_mode에 다음 수식어 중 하나 이상을 포함한 String을 넘기면 ERB가 코드 생성을 조정해요.

% enables Ruby code processing for lines beginning with %
<> omit newline for lines starting with <% and ending in %>
> omit newline for lines ending in %>
- omit blank lines ending in -%>

eoutvarERB가 출력을 쌓을 변수 이름을 정하는 데 써요. 같은 바인딩으로 여러 ERB 템플릿을 실행해야 하거나 출력이 어디로 갈지 제어하고 싶을 때 유용해요. 변수 이름을 String 안에 넣어 전달하면 돼요.

safe_level, legacy_trim_mode, legacy_eoutvar를 위치 인자로 넘기는 방식은 deprecated라 키워드 인자로 넘기는 걸 권장해요.

  • version() — erb.rb 모듈의 리비전 정보를 돌려줘요.

인스턴스 메서드

  • def_class(superklass=Object, methodname='result') — methodname을 인스턴스 메서드로 가진 이름 없는 클래스를 정의하고 돌려줘요.
class MyClass_
  def initialize(arg1, arg2)
    @arg1 = arg1; @arg2 = arg2
  end
end
filename = 'example.rhtml' # @arg1 and @arg2 are used in example.rhtml
erb = ERB.new(File.read(filename))
erb.filename = filename
MyClass = erb.def_class(MyClass_, 'render()')
print MyClass.new('foo', 123).render()
  • def_method(mod, methodname, fname='(ERB)') — 컴파일된 Ruby 소스에서 methodname을 mod의 인스턴스 메서드로 정의해요.
filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
erb = ERB.new(File.read(filename))
erb.def_method(MyClass, 'render(arg1, arg2)', filename)
print MyClass.new.render('foo', 123)
  • def_module(methodname='erb') — 이름 없는 모듈을 만들고 methodname을 그 인스턴스 메서드로 정의해 돌려줘요.
filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
erb = ERB.new(File.read(filename))
erb.filename = filename
MyModule = erb.def_module('render(arg1, arg2)')
class MyClass
  include MyModule
end
  • location=((filename, lineno))ERB 코드 평가와 오류 보고에 쓰일 선택적 filename과 줄 번호를 설정해요. filename=lineno=도 참고하세요.
erb = ERB.new('<%= some_x %>')
erb.render
# undefined local variable or method `some_x'
# from (erb):1

erb.location = ['file.erb', 3]
# 이후의 모든 오류 보고는 새 위치를 사용해요
erb.render
# undefined local variable or method `some_x'
# from file.erb:4
  • make_compiler(trim_mode)ERB용 새 컴파일러를 만들어요. ERB::Compiler.new 참고.
  • result(b=new_toplevel) — 생성된 ERB 코드를 실행해서 완성된 템플릿을 만들어 내고 결과를 돌려줘요. b는 코드 평가 컨텍스트를 설정하는 Binding 객체를 받아요.
  • result_with_hash(hash)Hash 객체로 지정한 지역 변수로 새 최상위 바인딩에서 템플릿을 렌더링해요.
  • run(b=new_toplevel) — 결과를 생성하고 출력해요. ERB#result 참고.
  • set_eoutvar(compiler, eoutvar = '_erbout')ERB::new에 설명된 대로 eoutvar를 설정하는 데 써요. 이 메서드는 ERB 컴파일러 객체 설정이 필요하니 보통은 생성자를 쓰는 게 더 쉬워요.

private 인스턴스 메서드

  • new_toplevel(vars = nil) — 바인딩을 지정하지 않는 실행을 위해 매번 TOPLEVEL_BINDING 근처의 새 바인딩을 돌려줘요.