Class: Tenjin::Engine

Inherits:
Object
  • Object
show all
Defined in:
lib/tenjin.rb

Overview

engine class for templates

Engine class supports the followings.

  • template caching

  • partial template

  • layout template

  • capturing (experimental)

ex. file ‘ex_list.rbhtml’

<ul>
<?rb for item in @items ?>
  <li>#{item}</li>
<?rb end ?>
</ul>

ex. file ‘ex_layout.rbhtml’

<html>
 <body>
  <h1>${@title}</li>
#{@_content}
<?rb import 'footer.rbhtml' ?>
 </body>
</html>

ex. file ‘main.rb’

require 'tenjin'
options = {:prefix=>'ex_', :postfix=>'.rbhtml', :layout=>'ex_layout.rbhtml'}
engine = Tenjin::Engine.new(options)
context = {:title=>'Tenjin Example', :items=>['foo', 'bar', 'baz']}
output = engine.render(:list, context)  # or 'ex_list.rbhtml'
print output

Direct Known Subclasses

SafeEngine

Constant Summary collapse

TIMESTAMP_INTERVAL =
1.0
@@template_cache =
FileBaseTemplateCache.new()
@@data_cache =
MemoryBaseStore.new()

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Engine

initializer of Engine class.

options:

:prefix

prefix string for template name (ex. ‘template/’)

:postfix

postfix string for template name (ex. ‘.rbhtml’)

:layout

layout template name (default nil)

:path

array of directory name (default nil)

:cache

save converted ruby code into file or not (default true)

:path

list of directory (default nil)

:preprocess

flag to activate preprocessing (default nil)

:templateclass

template class object (default Tenjin::Template)



1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
# File 'lib/tenjin.rb', line 1355

def initialize(options={})
  @prefix  = options[:prefix]  || ''
  @postfix = options[:postfix] || ''
  @layout  = options[:layout]
  @path    = options[:path]
  @lang    = options[:lang]
  @finder  = options[:finder] || FileFinder.new
  @cache   = _template_cache(options[:cache])
  @preprocess = options.fetch(:preprocess, nil)
  @data_cache = options[:data_cache] || @@data_cache
  @templateclass = options.fetch(:templateclass, Template)
  @init_opts_for_template = options
  @_templates = {}   # template_name => [template_obj, filepath]
end

Instance Attribute Details

#cacheObject

Returns the value of attribute cache.



1369
1370
1371
# File 'lib/tenjin.rb', line 1369

def cache
  @cache
end

#data_cacheObject

Returns the value of attribute data_cache.



1370
1371
1372
# File 'lib/tenjin.rb', line 1370

def data_cache
  @data_cache
end

#langObject

Returns the value of attribute lang.



1369
1370
1371
# File 'lib/tenjin.rb', line 1369

def lang
  @lang
end

#layoutObject

Returns the value of attribute layout.



1369
1370
1371
# File 'lib/tenjin.rb', line 1369

def layout
  @layout
end

#pathObject

Returns the value of attribute path.



1369
1370
1371
# File 'lib/tenjin.rb', line 1369

def path
  @path
end

#postfixObject

Returns the value of attribute postfix.



1369
1370
1371
# File 'lib/tenjin.rb', line 1369

def postfix
  @postfix
end

#prefixObject

Returns the value of attribute prefix.



1369
1370
1371
# File 'lib/tenjin.rb', line 1369

def prefix
  @prefix
end

#preprocessObject

Returns the value of attribute preprocess.



1370
1371
1372
# File 'lib/tenjin.rb', line 1370

def preprocess
  @preprocess
end

#templateclassObject

Returns the value of attribute templateclass.



1370
1371
1372
# File 'lib/tenjin.rb', line 1370

def templateclass
  @templateclass
end

Class Method Details

.data_cacheObject



1389
# File 'lib/tenjin.rb', line 1389

def self.data_cache;     @@data_cache;     end

.data_cache=(x) ⇒ Object



1390
# File 'lib/tenjin.rb', line 1390

def self.data_cache=(x); @@data_cache = x; end

.template_cacheObject



1385
# File 'lib/tenjin.rb', line 1385

def self.template_cache;     @@template_cache;     end

.template_cache=(x) ⇒ Object



1386
# File 'lib/tenjin.rb', line 1386

def self.template_cache=(x); @@template_cache = x; end

Instance Method Details

#cachename(filepath) ⇒ Object

returns cache file path of template file



1402
1403
1404
1405
1406
1407
1408
1409
1410
# File 'lib/tenjin.rb', line 1402

def cachename(filepath)
  #: if lang is provided then add it to cache filename.
  if @lang
    return "#{filepath}.#{@lang}.cache".untaint
  #: return cache file name which is untainted.
  else
    return "#{filepath}.cache".untaint
  end
end

#get_template(template_name, _context = nil) ⇒ Object



1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
# File 'lib/tenjin.rb', line 1474

def get_template(template_name, _context=nil)
  #: accept template name such as :index.
  filename = to_filename(template_name)
  #: if template object is in memory cache then return it.
  template = _get_template_in_memory(filename)
  return template if template
  #: if template file is not found then raise TemplateNotFoundError.
  filepath = @finder.find(filename, @path)  or
    raise TemplateNotFoundError.new("#{filename}: template not found (path=#{@path.inspect}).")
  #: if template is cached in file then store it into memory and return it.
  cachepath = cachename(filepath)
  template = _get_template_in_cache(filepath, cachepath)
  if template
    @_templates[filename] = [template, filepath]
    return template
  end
  #: if template file is not found then raises TemplateNotFoundError.
  ret = @finder.read(filepath)  or
    raise TemplateNotFoundError.new("#{filepath}: template not found.")
  input, timestamp = ret
  #: if preprocess is enabled then preprocess template file.
  input = _preprocess(input, filepath, _context) if @preprocess
  #: if template is not found in memory nor cache then create new one.
  template = create_template(input, filepath)
  template.filename = filepath
  template.timestamp = timestamp
  template._last_checked_at = Time.now
  #: save template object into file cache and memory cache.
  @cache.save(cachepath, template) if @cache
  @_templates[filename] = [template, filepath]
  #: return template object.
  return template
end

#register_template(template_name, template) ⇒ Object

register template object



1395
1396
1397
1398
1399
# File 'lib/tenjin.rb', line 1395

def register_template(template_name, template)
  #: register template object without file path.
  filename = to_filename(template_name)
  @_templates[filename] = [template, nil]
end

#render(template_name, context = Context.new, layout = true) ⇒ Object

get template object and evaluate it with context object. if argument ‘layout’ is true then default layout file (specified at initializer) is used as layout template, else if false then no layout template is used. if argument ‘layout’ is string, it is regarded as layout template name.



1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
# File 'lib/tenjin.rb', line 1562

def render(template_name, context=Context.new, layout=true)
  #: if context is a Hash object, convert it into Context object.
  context = hook_context(context)
  while true
    # get template
    template = get_template(template_name, context)  # context is passed only for preprocessor
    #: set template object into context (required for cache_with() helper)
    _tmpl = context._template
    context._template = template
    # render template
    output = template.render(context)
    # back template
    context._template = _tmpl
    #: if @_layout is specified, use it as layoute template name
    unless context._layout.nil?
      layout = context._layout
      context._layout = nil
    end
    #: use default layout template if layout is true or nil
    layout = @layout if layout == true || layout.nil?
    #: if layout is false then don't use layout template
    break unless layout
    #: set layout name as next template name
    template_name = layout
    layout = false
    #: set output into @_content for layout template
    context.instance_variable_set('@_content', output)
  end
  return output
end

#to_filename(template_name) ⇒ Object

convert short name into filename (ex. ‘:list’ => ‘template/list.rb.html’)



1413
1414
1415
1416
1417
1418
# File 'lib/tenjin.rb', line 1413

def to_filename(template_name)
  #: if template_name is a Symbol, add prefix and postfix to it.
  #: if template_name is not a Symbol, just return it.
  name = template_name
  return name.is_a?(Symbol) ? "#{@prefix}#{name}#{@postfix}" : name
end