類別 ERB
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)
列印: x 的值是:42
更複雜的範例如下。
識別的標籤¶ ↑
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_ 是 Big5。
範例¶ ↑
純文字¶ ↑
ERB
適用於任何一般範本情境。請注意,在此範例中,我們使用方便的「行首 %」標籤,並使用 %q{...}
逐字引用範本,以避免反斜線造成的問題。
require "erb" # Create template. 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: "%<>") # Set up template data. to = "Community Spokesman <spokesman@ruby_community.org>" priorities = [ "Run Ruby Quiz", "Document Modules", "Answer Questions on Ruby Talk" ] # Produce result. email = message.result puts email
產生
From: James Edward Gray II <[email protected]> To: Community Spokesman <spokesman@ruby_community.org> Subject: Addressing Needs Community: 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: * Run Ruby Quiz * Document Modules * Answer Questions on Ruby Talk Thanks for your patience. James Edward Gray II
HTML 中的 Ruby¶ ↑
ERB
通常用於 .rhtml
檔案(包含嵌入式 Ruby 的 HTML)。請注意,在此範例中,當執行範本時,需要提供特殊繫結,才能解析 Product 物件中的實例變數。
require "erb" # Build template data class. 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 # Support templating of member data. def get_binding binding end # ... end # Create template. 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) # Set up template data. 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!") # Produce result. rhtml.run(toy.get_binding)
產生(移除部分空白行)
<html> <head><title>Ruby Toys -- Rubysapien</title></head> <body> <h1>Rubysapien (TZ-1002)</h1> <p>Geek's Best Friend! Responds to Ruby commands...</p> <ul> <li><b>Listens for verbal commands in the Ruby language!</b></li> <li><b>Ignores Perl, Java, and all C variants.</b></li> <li><b>Karate-Chop Action!!!</b></li> <li><b>Matz signature on left leg.</b></li> <li><b>Gem studded eyes... Rubies, of course!</b></li> </ul> <p> Call for a price, today! </p> </body> </html>
備註¶ ↑
在各種 Ruby 專案中,有各式各樣的範本解決方案。例如,Ruby 內建的 RDoc
使用自己的範本引擎,可以在其他地方重複使用。
其他熱門引擎可以在 The Ruby Toolbox 的相應 類別 中找到。
常數
- NOT_GIVEN
- VERSION
屬性
要 eval 的編碼
執行 ERB
程式碼時,傳遞給 Kernel#eval
的選用 檔名 參數
執行 ERB
程式碼時,傳遞給 Kernel#eval
的選用 行號 參數
由 ERB
產生的 Ruby 程式碼
公開類別方法
使用 str 中指定的範本,建構新的 ERB
物件。
一個 ERB
物件透過建立一個 Ruby 程式碼區塊來運作,執行時會輸出已完成的範本。
如果 trim_mode 傳遞一個 字串
,其中包含下列一個或多個修飾詞,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
範本時很有用,或者當您想要控制輸出結果時。在 字串
內傳遞要使用的變數名稱。
範例¶ ↑
require "erb" # build data class class Listings PRODUCT = { :name => "Chicken Fried Steak", :desc => "A well messages pattie, breaded and fried.", :cost => 9.95 } attr_reader :product, :price def initialize( product = "", price = "" ) @product = product @price = price end def build b = binding # create and run templates, filling member data variables ERB.new(<<~'END_PRODUCT', trim_mode: "", eoutvar: "@product").result b <%= PRODUCT[:name] %> <%= PRODUCT[:desc] %> END_PRODUCT ERB.new(<<~'END_PRICE', trim_mode: "", eoutvar: "@price").result b <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %> <%= PRODUCT[:desc] %> END_PRICE end end # setup template data listings = Listings.new listings.build puts listings.product + "\n" + listings.price
產生
Chicken Fried Steak A well messages pattie, breaded and fried. Chicken Fried Steak -- 9.95 A well messages pattie, breaded and fried.
# File lib/erb.rb, line 334 def initialize(str, safe_level=NOT_GIVEN, legacy_trim_mode=NOT_GIVEN, legacy_eoutvar=NOT_GIVEN, trim_mode: nil, eoutvar: '_erbout') # Complex initializer for $SAFE deprecation at [Feature #14256]. Use keyword arguments to pass trim_mode or eoutvar. if safe_level != NOT_GIVEN warn 'Passing safe_level with the 2nd argument of ERB.new is deprecated. Do not use it, and specify other arguments as keyword arguments.', uplevel: 1 end if legacy_trim_mode != NOT_GIVEN warn 'Passing trim_mode with the 3rd argument of ERB.new is deprecated. Use keyword argument like ERB.new(str, trim_mode: ...) instead.', uplevel: 1 trim_mode = legacy_trim_mode end if legacy_eoutvar != NOT_GIVEN warn 'Passing eoutvar with the 4th argument of ERB.new is deprecated. Use keyword argument like ERB.new(str, eoutvar: ...) instead.', uplevel: 1 eoutvar = legacy_eoutvar end compiler = make_compiler(trim_mode) set_eoutvar(compiler, eoutvar) @src, @encoding, @frozen_string = *compiler.compile(str) @filename = nil @lineno = 0 @_init = self.class.singleton_class end
傳回 erb.rb 模組的版本資訊。
# File lib/erb.rb, line 266 def self.version VERSION end
公開實例方法
定義未命名類別,其具有 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()
# File lib/erb.rb, line 500 def def_class(superklass=Object, methodname='result') cls = Class.new(superklass) def_method(cls, methodname, @filename || '(ERB)') cls end
從編譯的 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)
# File lib/erb.rb, line 464 def def_method(mod, methodname, fname='(ERB)') src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n" mod.module_eval do eval(src, binding, fname, -1) end end
建立未命名模組,定義 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
# File lib/erb.rb, line 481 def def_module(methodname='erb') mod = Module.new def_method(mod, methodname, @filename || '(ERB)') mod end
設定 ERB
程式碼評估和錯誤回報中將使用的選用檔案名稱和行號。另請參閱 filename=
和 lineno=
erb = ERB.new('<%= some_x %>') erb.render # undefined local variable or method `some_x' # from (erb):1 erb.location = ['file.erb', 3] # All subsequent error reporting would use new location erb.render # undefined local variable or method `some_x' # from file.erb:4
# File lib/erb.rb, line 394 def location=((filename, lineno)) @filename = filename @lineno = lineno if lineno end
為 ERB
建立新的編譯器。有關詳細資訊,請參閱 ERB::Compiler.new
# File lib/erb.rb, line 361 def make_compiler(trim_mode) ERB::Compiler.new(trim_mode) end
執行已產生的 ERB
程式碼以產生已完成的範本,傳回該程式碼的結果。(有關此程序如何受到 safe_level 影響的詳細資訊,請參閱 ERB::new
。)
b 接受 Binding
物件,用於設定程式碼評估的內容。
# File lib/erb.rb, line 424 def result(b=new_toplevel) unless @_init.equal?(self.class.singleton_class) raise ArgumentError, "not initialized" end eval(@src, b, (@filename || '(erb)'), @lineno) end
使用 Hash
物件指定的區域變數,在新的頂層繫結上呈現範本。
# File lib/erb.rb, line 433 def result_with_hash(hash) b = new_toplevel(hash.keys) hash.each_pair do |key, value| b.local_variable_set(key, value) end result(b) end
產生結果並列印出來。(請參閱 ERB#result
)
# File lib/erb.rb, line 412 def run(b=new_toplevel) print self.result(b) end
私有執行個體方法
每次針對未指定繫結的執行,傳回接近 TOPLEVEL_BINDING 的新繫結。
# File lib/erb.rb, line 445 def new_toplevel(vars = nil) b = TOPLEVEL_BINDING if vars vars = vars.select {|v| b.local_variable_defined?(v)} unless vars.empty? return b.eval("tap {|;#{vars.join(',')}| break binding}") end end b.dup end