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)



1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
# File 'lib/tenjin.rb', line 1344

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.



1358
1359
1360
# File 'lib/tenjin.rb', line 1358

def cache
  @cache
end

#data_cacheObject

Returns the value of attribute data_cache.



1359
1360
1361
# File 'lib/tenjin.rb', line 1359

def data_cache
  @data_cache
end

#langObject

Returns the value of attribute lang.



1358
1359
1360
# File 'lib/tenjin.rb', line 1358

def lang
  @lang
end

#layoutObject

Returns the value of attribute layout.



1358
1359
1360
# File 'lib/tenjin.rb', line 1358

def layout
  @layout
end

#pathObject

Returns the value of attribute path.



1358
1359
1360
# File 'lib/tenjin.rb', line 1358

def path
  @path
end

#postfixObject

Returns the value of attribute postfix.



1358
1359
1360
# File 'lib/tenjin.rb', line 1358

def postfix
  @postfix
end

#prefixObject

Returns the value of attribute prefix.



1358
1359
1360
# File 'lib/tenjin.rb', line 1358

def prefix
  @prefix
end

#preprocessObject

Returns the value of attribute preprocess.



1359
1360
1361
# File 'lib/tenjin.rb', line 1359

def preprocess
  @preprocess
end

#templateclassObject

Returns the value of attribute templateclass.



1359
1360
1361
# File 'lib/tenjin.rb', line 1359

def templateclass
  @templateclass
end

Class Method Details

.data_cacheObject



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

def self.data_cache;     @@data_cache;     end

.data_cache=(x) ⇒ Object



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

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

.template_cacheObject



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

def self.template_cache;     @@template_cache;     end

.template_cache=(x) ⇒ Object



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

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

Instance Method Details

#cachename(filepath) ⇒ Object

returns cache file path of template file



1391
1392
1393
1394
1395
1396
1397
1398
1399
# File 'lib/tenjin.rb', line 1391

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



1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
# File 'lib/tenjin.rb', line 1463

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



1384
1385
1386
1387
1388
# File 'lib/tenjin.rb', line 1384

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.



1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
# File 'lib/tenjin.rb', line 1551

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’)



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

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