class Template

Base class for template implementations. Subclasses must implement the prepare method and one of the evaluate or precompiled_template methods.

Attributes

data[R]

Template source; loaded from a file or given directly.

file[R]

The name of the file where the template data was loaded from.

line[R]

The line number in file where template data was loaded from.

options[R]

A Hash of template engine specific options. This is passed directly to the underlying engine and is not used by the generic template interface.

Public Class Methods

default_mime_type() click to toggle source

@deprecated Use ‘.metadata` instead.

   # File lib/tilt/template.rb
44 def default_mime_type
45   metadata[:mime_type]
46 end
default_mime_type=(value) click to toggle source

@deprecated Use ‘.metadata = val` instead.

   # File lib/tilt/template.rb
49 def default_mime_type=(value)
50   metadata[:mime_type] = value
51 end
metadata() click to toggle source

An empty Hash that the template engine can populate with various metadata.

   # File lib/tilt/template.rb
39 def metadata
40   @metadata ||= {}
41 end
new(file=nil, line=1, options={}, &block) click to toggle source

Create a new template with the file, line, and options specified. By default, template data is read from the file. When a block is given, it should read template data and return as a String. When file is nil, a block is required.

All arguments are optional.

    # File lib/tilt/template.rb
 60 def initialize(file=nil, line=1, options={}, &block)
 61   @file, @line, @options = nil, 1, {}
 62 
 63   [options, line, file].compact.each do |arg|
 64     case
 65     when arg.respond_to?(:to_str)  ; @file = arg.to_str
 66     when arg.respond_to?(:to_int)  ; @line = arg.to_int
 67     when arg.respond_to?(:to_hash) ; @options = arg.to_hash.dup
 68     when arg.respond_to?(:path)    ; @file = arg.path
 69     when arg.respond_to?(:to_path) ; @file = arg.to_path
 70     else raise TypeError, "Can't load the template file. Pass a string with a path " +
 71       "or an object that responds to 'to_str', 'path' or 'to_path'"
 72     end
 73   end
 74 
 75   raise ArgumentError, "file or block required" if (@file || block).nil?
 76 
 77   # used to hold compiled template methods
 78   @compiled_method = {}
 79 
 80   # used on 1.9 to set the encoding if it is not set elsewhere (like a magic comment)
 81   # currently only used if template compiles to ruby
 82   @default_encoding = @options.delete :default_encoding
 83 
 84   # load template data and prepare (uses binread to avoid encoding issues)
 85   @reader = block || lambda { |t| read_template_file }
 86   @data = @reader.call(self)
 87 
 88   if @data.respond_to?(:force_encoding)
 89     if default_encoding
 90       @data = @data.dup if @data.frozen?
 91       @data.force_encoding(default_encoding)
 92     end
 93 
 94     if !@data.valid_encoding?
 95       raise Encoding::InvalidByteSequenceError, "#{eval_file} is not valid #{@data.encoding}"
 96     end
 97   end
 98 
 99   prepare
100 end

Public Instance Methods

basename(suffix='') click to toggle source

The basename of the template file.

    # File lib/tilt/template.rb
115 def basename(suffix='')
116   File.basename(file, suffix) if file
117 end
eval_file() click to toggle source

The filename used in backtraces to describe the template.

    # File lib/tilt/template.rb
125 def eval_file
126   file || '(__TEMPLATE__)'
127 end
metadata() click to toggle source

An empty Hash that the template engine can populate with various metadata.

    # File lib/tilt/template.rb
131 def metadata
132   if respond_to?(:allows_script?)
133     self.class.metadata.merge(:allows_script => allows_script?)
134   else
135     self.class.metadata
136   end
137 end
name() click to toggle source

The template file’s basename with all extensions chomped off.

    # File lib/tilt/template.rb
120 def name
121   basename.split('.', 2).first if basename
122 end
render(scope=nil, locals={}, &block) click to toggle source

Render the template in the given scope with the locals specified. If a block is given, it is typically available within the template via yield.

    # File lib/tilt/template.rb
105 def render(scope=nil, locals={}, &block)
106   scope ||= Object.new
107   current_template = Thread.current[:tilt_current_template]
108   Thread.current[:tilt_current_template] = self
109   evaluate(scope, locals || {}, &block)
110 ensure
111   Thread.current[:tilt_current_template] = current_template
112 end

Protected Instance Methods

default_encoding() click to toggle source

The encoding of the source data. Defaults to the default_encoding-option if present. You may override this method in your template class if you have a better hint of the data’s encoding.

    # File lib/tilt/template.rb
147 def default_encoding
148   @default_encoding
149 end
evaluate(scope, locals, &block) click to toggle source

Execute the compiled template and return the result string. Template evaluation is guaranteed to be performed in the scope object with the locals specified and with support for yielding to the block.

This method is only used by source generating templates. Subclasses that override render() may not support all features.

    # File lib/tilt/template.rb
166 def evaluate(scope, locals, &block)
167   locals_keys = locals.keys
168   locals_keys.sort!{|x, y| x.to_s <=> y.to_s}
169   method = compiled_method(locals_keys, scope.is_a?(Module) ? scope : scope.class)
170   method.bind(scope).call(locals, &block)
171 end
precompiled(local_keys) click to toggle source

Generates all template source by combining the preamble, template, and postamble and returns a two-tuple of the form: [source, offset], where source is the string containing (Ruby) source code for the template and offset is the integer line offset where line reporting should begin.

Template subclasses may override this method when they need complete control over source generation or want to adjust the default line offset. In most cases, overriding the precompiled_template method is easier and more appropriate.

    # File lib/tilt/template.rb
182 def precompiled(local_keys)
183   preamble = precompiled_preamble(local_keys)
184   template = precompiled_template(local_keys)
185   postamble = precompiled_postamble(local_keys)
186   source = String.new
187 
188   # Ensure that our generated source code has the same encoding as the
189   # the source code generated by the template engine.
190   if source.respond_to?(:force_encoding)
191     template_encoding = extract_encoding(template)
192 
193     source.force_encoding(template_encoding)
194     template.force_encoding(template_encoding)
195   end
196 
197   source << preamble << "\n" << template << "\n" << postamble
198 
199   [source, preamble.count("\n")+1]
200 end
precompiled_postamble(local_keys) click to toggle source
    # File lib/tilt/template.rb
216 def precompiled_postamble(local_keys)
217   ''
218 end
precompiled_preamble(local_keys) click to toggle source
    # File lib/tilt/template.rb
212 def precompiled_preamble(local_keys)
213   ''
214 end
precompiled_template(local_keys) click to toggle source

A string containing the (Ruby) source code for the template. The default Template#evaluate implementation requires either this method or the precompiled method be overridden. When defined, the base Template guarantees correct file/line handling, locals support, custom scopes, proper encoding, and support for template compilation.

    # File lib/tilt/template.rb
208 def precompiled_template(local_keys)
209   raise NotImplementedError
210 end
prepare() click to toggle source

Do whatever preparation is necessary to setup the underlying template engine. Called immediately after template data is loaded. Instance variables set in this method are available when evaluate is called.

Subclasses must provide an implementation of this method.

    # File lib/tilt/template.rb
156 def prepare
157   raise NotImplementedError
158 end

Private Instance Methods

binary(string) { || ... } click to toggle source
    # File lib/tilt/template.rb
289 def binary(string)
290   original_encoding = string.encoding
291   string.force_encoding(Encoding::BINARY)
292   yield
293 ensure
294   string.force_encoding(original_encoding)
295 end
compile_template_method(local_keys, scope_class=nil) click to toggle source
    # File lib/tilt/template.rb
250     def compile_template_method(local_keys, scope_class=nil)
251       source, offset = precompiled(local_keys)
252       local_code = local_extraction(local_keys)
253 
254       method_name = "__tilt_#{Thread.current.object_id.abs}"
255       method_source = String.new
256 
257       if method_source.respond_to?(:force_encoding)
258         method_source.force_encoding(source.encoding)
259       end
260 
261       method_source << <<-RUBY
262         TOPOBJECT.class_eval do
263           def #{method_name}(locals)
264             #{local_code}
265       RUBY
266       offset += method_source.count("\n")
267       method_source << source
268       method_source << "\nend;end;"
269       (scope_class || Object).class_eval(method_source, eval_file, line - offset)
270       unbind_compiled_method(method_name)
271     end
compiled_method(locals_keys, scope_class=nil) click to toggle source

The compiled method for the locals keys provided.

    # File lib/tilt/template.rb
234 def compiled_method(locals_keys, scope_class=nil)
235   LOCK.synchronize do
236     @compiled_method[[scope_class, locals_keys]] ||= compile_template_method(locals_keys, scope_class)
237   end
238 end
extract_encoding(script) click to toggle source
    # File lib/tilt/template.rb
279 def extract_encoding(script)
280   extract_magic_comment(script) || script.encoding
281 end
extract_magic_comment(script) click to toggle source
    # File lib/tilt/template.rb
283 def extract_magic_comment(script)
284   binary(script) do
285     script[/\A[ \t]*\#.*coding\s*[=:]\s*([[:alnum:]\-_]+).*$/n, 1]
286   end
287 end
local_extraction(local_keys) click to toggle source
    # File lib/tilt/template.rb
240 def local_extraction(local_keys)
241   local_keys.map do |k|
242     if k.to_s =~ /\A[a-z_][a-zA-Z_0-9]*\z/
243       "#{k} = locals[#{k.inspect}]"
244     else
245       raise "invalid locals key: #{k.inspect} (keys must be variable names)"
246     end
247   end.join("\n")
248 end
read_template_file() click to toggle source

!@endgroup

    # File lib/tilt/template.rb
224 def read_template_file
225   data = File.open(file, 'rb') { |io| io.read }
226   if data.respond_to?(:force_encoding)
227     # Set it to the default external (without verifying)
228     data.force_encoding(Encoding.default_external) if Encoding.default_external
229   end
230   data
231 end
unbind_compiled_method(method_name) click to toggle source
    # File lib/tilt/template.rb
273 def unbind_compiled_method(method_name)
274   method = TOPOBJECT.instance_method(method_name)
275   TOPOBJECT.class_eval { remove_method(method_name) }
276   method
277 end