Object
Base class for template implementations. Subclasses must implement the # method and one of the # or # methods.
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/sinatra/tilt.rb, line 96 96: def initialize(file=nil, line=1, options={}, &block) 97: @file, @line, @options = nil, 1, {} 98: 99: [options, line, file].compact.each do |arg| 100: case 101: when arg.respond_to?(:to_str) ; @file = arg.to_str 102: when arg.respond_to?(:to_int) ; @line = arg.to_int 103: when arg.respond_to?(:to_hash) ; @options = arg.to_hash 104: else raise TypeError 105: end 106: end 107: 108: raise ArgumentError, "file or block required" if (@file || block).nil? 109: 110: # call the initialize_engine method if this is the very first time 111: # an instance of this class has been created. 112: if !self.class.engine_initialized? 113: initialize_engine 114: self.class.engine_initialized = true 115: end 116: 117: # used to generate unique method names for template compilation 118: @stamp = (Time.now.to_f * 10000).to_i 119: @compiled_method_names = {} 120: 121: # load template data and prepare 122: @reader = block || lambda { |t| File.read(@file) } 123: @data = @reader.call(self) 124: prepare 125: end
# File lib/sinatra/tilt.rb, line 299 299: def self.compiled_template_method_remover(site, method_name) 300: proc { |oid| garbage_collect_compiled_template_method(site, method_name) } 301: end
# File lib/sinatra/tilt.rb, line 303 303: def self.garbage_collect_compiled_template_method(site, method_name) 304: site.module_eval do 305: begin 306: remove_method(method_name) 307: rescue NameError 308: # method was already removed (ruby >= 1.9) 309: end 310: end 311: end
The basename of the template file.
# File lib/sinatra/tilt.rb, line 135 135: def basename(suffix='') 136: File.basename(file, suffix) if file 137: end
The filename used in backtraces to describe the template.
# File lib/sinatra/tilt.rb, line 145 145: def eval_file 146: file || '(__TEMPLATE__)' 147: end
The template file’s basename with all extensions chomped off.
# File lib/sinatra/tilt.rb, line 140 140: def name 141: basename.split('.', 2).first if basename 142: end
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/sinatra/tilt.rb, line 130 130: def render(scope=Object.new, locals={}, &block) 131: evaluate scope, locals || {}, &block 132: end
The unique compiled method name for the locals keys provided.
# File lib/sinatra/tilt.rb, line 248 248: def compiled_method_name(locals_keys) 249: @compiled_method_names[locals_keys] ||= 250: generate_compiled_method_name(locals_keys) 251: end
Process the template and return the result. When the scope mixes in the Tilt::CompileSite module, the template is compiled to a method and reused given identical locals keys. When the scope object does not mix in the CompileSite module, the template source is evaluated with instance_eval. 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/sinatra/tilt.rb, line 188 188: def evaluate(scope, locals, &block) 189: if scope.respond_to?(:__tilt__) 190: method_name = compiled_method_name(locals.keys) 191: if scope.respond_to?(method_name) 192: scope.send(method_name, locals, &block) 193: else 194: compile_template_method(method_name, locals) 195: scope.send(method_name, locals, &block) 196: end 197: else 198: evaluate_source(scope, locals, &block) 199: end 200: end
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/sinatra/tilt.rb, line 153 153: def initialize_engine 154: end
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/sinatra/tilt.rb, line 211 211: def precompiled(locals) 212: preamble = precompiled_preamble(locals) 213: parts = [ 214: preamble, 215: precompiled_template(locals), 216: precompiled_postamble(locals) 217: ] 218: [parts.join("\n"), preamble.count("\n") + 1] 219: end
Generates postamble code for the precompiled template source. The string returned from this method is appended to the precompiled template source.
# File lib/sinatra/tilt.rb, line 243 243: def precompiled_postamble(locals) 244: '' 245: end
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/sinatra/tilt.rb, line 236 236: def precompiled_preamble(locals) 237: locals.map { |k,v| "#{k} = locals[:#{k}]" }.join("\n") 238: end
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/sinatra/tilt.rb, line 227 227: def precompiled_template(locals) 228: raise NotImplementedError 229: end
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/sinatra/tilt.rb, line 171 171: def prepare 172: if respond_to?(:compile!) 173: # backward compat with tilt < 0.6; just in case 174: warn 'Tilt::Template#compile! is deprecated; implement #prepare instead.' 175: compile! 176: else 177: raise NotImplementedError 178: end 179: end
Like Kernel::require but issues a warning urging a manual require when running under a threaded environment.
# File lib/sinatra/tilt.rb, line 158 158: def require_template_library(name) 159: if Thread.list.size > 1 160: warn "WARN: tilt autoloading '#{name}' in a non thread-safe way; " + 161: "explicit require '#{name}' suggested." 162: end 163: require name 164: end
# File lib/sinatra/tilt.rb, line 286 286: def compile_template_method(method_name, locals) 287: source, offset = precompiled(locals) 288: offset += 1 289: CompileSite.module_eval def #{method_name}(locals) #{source} end, eval_file, line - offset 290: 291: ObjectSpace.define_finalizer self, 292: Template.compiled_template_method_remover(CompileSite, method_name) 293: end
Evaluate the template source in the context of the scope object.
# File lib/sinatra/tilt.rb, line 255 255: def evaluate_source(scope, locals, &block) 256: source, offset = precompiled(locals) 257: scope.instance_eval(source, eval_file, line - offset) 258: end
# File lib/sinatra/tilt.rb, line 273 273: def evaluate_source(scope, locals, &block) 274: source, offset = precompiled(locals) 275: file, lineno = eval_file, (line - offset) - 1 276: scope.instance_eval { Kernel::eval(source, binding, file, lineno) } 277: end
# File lib/sinatra/tilt.rb, line 280 280: def generate_compiled_method_name(locals_keys) 281: parts = [object_id, @stamp] + locals_keys.map { |k| k.to_s }.sort 282: digest = Digest::MD5.hexdigest(parts.join(':')) 283: "__tilt_#{digest}" 284: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.