Parent

Tilt::Template

Base class for template implementations. Subclasses must implement the # method and one of the # or # 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 # 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.

engine_initialized[RW]
default_mime_type[RW]

Public Class Methods

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, line 38
38:     def initialize(file=nil, line=1, options={}, &block)
39:       @file, @line, @options = nil, 1, {}
40: 
41:       [options, line, file].compact.each do |arg|
42:         case
43:         when arg.respond_to?(:to_str)  ; @file = arg.to_str
44:         when arg.respond_to?(:to_int)  ; @line = arg.to_int
45:         when arg.respond_to?(:to_hash) ; @options = arg.to_hash.dup
46:         else raise TypeError
47:         end
48:       end
49: 
50:       raise ArgumentError, "file or block required" if (@file || block).nil?
51: 
52:       # call the initialize_engine method if this is the very first time
53:       # an instance of this class has been created.
54:       if !self.class.engine_initialized?
55:         initialize_engine
56:         self.class.engine_initialized = true
57:       end
58: 
59:       # used to hold compiled template methods
60:       @compiled_method = {}
61: 
62:       # used on 1.9 to set the encoding if it is not set elsewhere (like a magic comment)
63:       # currently only used if template compiles to ruby
64:       @default_encoding = @options.delete :default_encoding
65: 
66:       # load template data and prepare (uses binread to avoid encoding issues)
67:       @reader = block || lambda { |t| File.respond_to?(:binread) ? File.binread(@file) : File.read(@file) }
68:       @data = @reader.call(self)
69:       prepare
70:     end

Protected Class Methods

cached_evaluate(scope, locals, &block) click to toggle source

Redefine itself to use method compilation the next time:

     # File lib/tilt/template.rb, line 138
138:       def self.cached_evaluate(scope, locals, &block)
139:         method = compiled_method(locals.keys)
140:         method.bind(scope).call(locals, &block)
141:       end

Public Instance Methods

basename(suffix='') click to toggle source

The basename of the template file.

    # File lib/tilt/template.rb, line 80
80:     def basename(suffix='')
81:       File.basename(file, suffix) if file
82:     end
eval_file() click to toggle source

The filename used in backtraces to describe the template.

    # File lib/tilt/template.rb, line 90
90:     def eval_file
91:       file || '(__TEMPLATE__)'
92:     end
name() click to toggle source

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

    # File lib/tilt/template.rb, line 85
85:     def name
86:       basename.split('.', 2).first if basename
87:     end
render(scope=Object.new, 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, line 75
75:     def render(scope=Object.new, locals={}, &block)
76:       evaluate scope, locals || {}, &block
77:     end

Protected Instance Methods

cached_evaluate(scope, locals, &block) click to toggle source

Process the template and return the result. The first time this method is called, the template source is evaluated with instance_eval. On the sequential method calls it will compile the template to an unbound method which will lead to better performance. In any case, template executation is guaranteed to be performed in the scope object with the locals specified and with support for yielding to the block.

     # File lib/tilt/template.rb, line 136
136:     def cached_evaluate(scope, locals, &block)
137:       # Redefine itself to use method compilation the next time:
138:       def self.cached_evaluate(scope, locals, &block)
139:         method = compiled_method(locals.keys)
140:         method.bind(scope).call(locals, &block)
141:       end
142: 
143:       # Use instance_eval the first time:
144:       evaluate_source(scope, locals, &block)
145:     end
compiled_method(locals_keys) click to toggle source

The compiled method for the locals keys provided.

     # File lib/tilt/template.rb, line 200
200:     def compiled_method(locals_keys)
201:       @compiled_method[locals_keys] ||=
202:         compile_template_method(locals_keys)
203:     end
evaluate(scope, locals, &block) click to toggle source
     # File lib/tilt/template.rb, line 126
126:     def evaluate(scope, locals, &block)
127:       cached_evaluate(scope, locals, &block)
128:     end
initialize_engine() click to toggle source

Called once and only once for each template subclass the first time the template class is initialized. This should be used to require the underlying template library and perform any initial setup.

    # File lib/tilt/template.rb, line 98
98:     def initialize_engine
99:     end
precompiled(locals) 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 # method is easier and more appropriate.

     # File lib/tilt/template.rb, line 156
156:     def precompiled(locals)
157:       preamble = precompiled_preamble(locals)
158:       template = precompiled_template(locals)
159:       magic_comment = extract_magic_comment(template)
160:       if magic_comment
161:         # Magic comment e.g. "# coding: utf-8" has to be in the first line.
162:         # So we copy the magic comment to the first line.
163:         preamble = magic_comment + "\n" + preamble
164:       end
165:       parts = [
166:         preamble,
167:         template,
168:         precompiled_postamble(locals)
169:       ]
170:       [parts.join("\n"), preamble.count("\n") + 1]
171:     end
precompiled_postamble(locals) click to toggle source

Generates postamble code for the precompiled template source. The string returned from this method is appended to the precompiled template source.

     # File lib/tilt/template.rb, line 195
195:     def precompiled_postamble(locals)
196:       ''
197:     end
precompiled_preamble(locals) click to toggle source

Generates preamble code for initializing template state, and performing locals assignment. The default implementation performs locals assignment only. Lines included in the preamble are subtracted from the source line offset, so adding code to the preamble does not effect line reporting in Kernel::caller and backtraces.

     # File lib/tilt/template.rb, line 188
188:     def precompiled_preamble(locals)
189:       locals.map { |k,v| "#{k} = locals[#{k.inspect}]" }.join("\n")
190:     end
precompiled_template(locals) 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 # method be overridden. When defined, the base Template guarantees correct file/line handling, locals support, custom scopes, and support for template compilation when the scope object allows it.

     # File lib/tilt/template.rb, line 179
179:     def precompiled_template(locals)
180:       raise NotImplementedError
181:     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 # is called.

Subclasses must provide an implementation of this method.

     # File lib/tilt/template.rb, line 116
116:     def prepare
117:       if respond_to?(:compile!)
118:         # backward compat with tilt < 0.6; just in case
119:         warn 'Tilt::Template#compile! is deprecated; implement #prepare instead.'
120:         compile!
121:       else
122:         raise NotImplementedError
123:       end
124:     end
require_template_library(name) click to toggle source

Like Kernel::require but issues a warning urging a manual require when running under a threaded environment.

     # File lib/tilt/template.rb, line 103
103:     def require_template_library(name)
104:       if Thread.list.size > 1
105:         warn "WARN: tilt autoloading '#{name}' in a non thread-safe way; " +
106:              "explicit require '#{name}' suggested."
107:       end
108:       require name
109:     end

Private Instance Methods

compile_template_method(locals) click to toggle source
     # File lib/tilt/template.rb, line 229
229:     def compile_template_method(locals)
230:       source, offset = precompiled(locals)
231:       offset += 5
232:       method_name = "__tilt_#{Thread.current.object_id.abs}"
233:       Object.class_eval         #{extract_magic_comment source}        TOPOBJECT.class_eval do          def #{method_name}(locals)            Thread.current[:tilt_vars] = [self, locals]            class << self              this, locals = Thread.current[:tilt_vars]              this.instance_eval do               #{source}              end            end          end        end, eval_file, line - offset
234:       unbind_compiled_method(method_name)
235:     end
compile_template_method(locals) click to toggle source
     # File lib/tilt/template.rb, line 270
270:       def compile_template_method(locals)
271:         source, offset = precompiled(locals)
272:         offset += 1
273:         method_name = "__tilt_#{Thread.current.object_id}"
274:         Object.class_eval           TOPOBJECT.class_eval do            def #{method_name}(locals)              #{source}            end          end, eval_file, line - offset
275:         unbind_compiled_method(method_name)
276:       end
evaluate_source(scope, locals, &block) click to toggle source

Evaluate the template source in the context of the scope object.

     # File lib/tilt/template.rb, line 207
207:     def evaluate_source(scope, locals, &block)
208:       source, offset = precompiled(locals)
209:       scope.instance_eval(source, eval_file, line - offset)
210:     end
evaluate_source(scope, locals, &block) click to toggle source
     # File lib/tilt/template.rb, line 222
222:       def evaluate_source(scope, locals, &block)
223:         source, offset = precompiled(locals)
224:         file, lineno = eval_file, (line - offset)
225:         scope.instance_eval { Kernel::eval(source, binding, file, lineno) }
226:       end
extract_magic_comment(script) click to toggle source
     # File lib/tilt/template.rb, line 256
256:     def extract_magic_comment(script)
257:       comment = script.slice(/\A[ \t]*\#.*coding\s*[=:]\s*([[:alnum:]\-_]+).*$/)
258:       return comment if comment and not ]ascii-8bit binary].include?($1.downcase)
259:       "# coding: #{@default_encoding}" if @default_encoding
260:     end
unbind_compiled_method(method_name) click to toggle source
     # File lib/tilt/template.rb, line 250
250:     def unbind_compiled_method(method_name)
251:       method = TOPOBJECT.instance_method(method_name)
252:       TOPOBJECT.class_eval { remove_method(method_name) }
253:       method
254:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.