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.new와 ERB#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_GIVENVERSION
속성
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 -%>
eoutvar는 ERB가 출력을 쌓을 변수 이름을 정하는 데 써요. 같은 바인딩으로 여러 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근처의 새 바인딩을 돌려줘요.