class Malt::Engine::Abstract

Abstract Template class serves as the base class for all other Template classes.

Attributes

settings[R]

Access to the options given to the initializer.

Public Class Methods

default(*exts) click to toggle source

Register and set as the default for given extensions.

# File lib/malt/engines/abstract.rb, line 42
def self.default(*exts)
  register(*exts)
  exts.each do |ext|
    Engine.defaults[ext.to_sym] = self
  end
end
new(settings={}) click to toggle source
# File lib/malt/engines/abstract.rb, line 55
def initialize(settings={})
  @settings = settings.rekey

  @cache  = {}
  @source = {}

  require_engine
end
register(*exts) click to toggle source

Register the class to an extension type.

# File lib/malt/engines/abstract.rb, line 37
def self.register(*exts)
  Engine.register(self, *exts)
end
type() click to toggle source
# File lib/malt/engines/abstract.rb, line 50
def self.type
  basename.downcase.to_sym
end

Public Instance Methods

cache?() click to toggle source
# File lib/malt/engines/abstract.rb, line 68
def cache?
  !settings[:nocache]
end
create_engine(params={}) click to toggle source

Instantiate engine class with engine options and template text, if possible.

The initialization MUST never include template data and should support caching, if feasible.

# File lib/malt/engines/abstract.rb, line 92
def create_engine(params={})
  raise NotImplementedError, "not implemented"
end
prepare_engine(params={}, &content) click to toggle source

Prepare engine for rendering.

# File lib/malt/engines/abstract.rb, line 82
def prepare_engine(params={}, &content)
  create_engine(params, &content)
end
render(params, &block) click to toggle source
# File lib/malt/engines/abstract.rb, line 73
def render(params, &block)
  if into = params[:to]
    raise NotImplementedError, "unsupported rendering -- #{into}"
  else
    raise NotImplementedError, "unsupported rendering"
  end
end

Private Instance Methods

cached(*key) { || ... } click to toggle source

Cached yield reuslt with given key if cache mode is active.

# File lib/malt/engines/abstract.rb, line 106
def cached(*key)
  if cache?
    @cache[key] ||= yield
  else
    yield
  end
end
engine_option_names() click to toggle source

Override this.

# File lib/malt/engines/abstract.rb, line 349
def engine_option_names
  []
end
engine_options(params) click to toggle source
# File lib/malt/engines/abstract.rb, line 338
def engine_options(params)
  opts = {}
  engine_option_names.each do |o|
    o = o.to_sym
    v = params[o] || settings[o]
    opts[o] = v if v
  end
  opts
end
make_binding(scope, locals=nil, &content) click to toggle source

Convert scope and data into a Binding.

@param [Object,Binding,Hash,Array] data

The data source used for evaluation.

@see split_data

@return [Object] The data and yield block converted to a Binding.

# File lib/malt/engines/abstract.rb, line 205
def make_binding(scope, locals=nil, &content)
  case scope
  when Binding
    locals ||= {}
    locals[:content] = content.call if content
    scope.with(locals)
  else
    scope, locals = make_ready(scope, locals, &content)
    scope.to_binding.with(locals)
  end
end
make_external(scope, locals=nil, &content) click to toggle source

Take scope and locals are return the same reworked for use as externalized template variables.

@return [Array<Object,Hash>]

Two element array of scope object and data hash.
# File lib/malt/engines/abstract.rb, line 167
def make_external(scope, locals=nil, &content)
  locals ||= {}

  case scope
  when Binding
    vars   = scope.eval("local_variables")
    vals   = scope.eval("[#{vars.join(',')}]")
    locals = locals.merge(Hash[*vars.zip(vals).flatten])
    scope  = scope.eval("self")
  end

  if scope.respond_to?(:to_struct)
    locals = locals.merge(scope.to_struct.to_h)
    #scope  = Object.new
  end

  if scope.respond_to?(:to_hash)
    locals = locals.merge(scope.to_hash)
    scope  = Object.new
  end

  scope ||= Object.new
  scope = make_object(scope || Object.new)

  locals[:scope]   = scope
  locals[:content] = content.call if content

  return scope, locals
end
make_hash(scope, locals=nil, &content) click to toggle source

Convert data source into a hash.

@param [Object,Binding,Hash,Array] data

The data source used for evaluation.

@see scope_vs_hash

@return [Hash] The data and yield block converted to a Hash.

# File lib/malt/engines/abstract.rb, line 297
def make_hash(scope, locals=nil, &content)
  case scope
  when nil
    hash = locals || {}
  when Binding
    #hash = Hash.new{ |h,k| p h,k; h[k] = data.key?(k) ? data[k] : scope.eval(k) }
    hash = Hash.new{ |h,k| h[k] = scope.eval(k) }
  else
    if scope.respond_to?(:to_hash)
      hash = scope.to_hash.merge(data)
    else
      #hash = Hash.new{ |h,k| data.key?(k) ? data[k] : h[k] = scope.__send__(k) }
      hash = Hash.new{ |h,k| h[k] = scope.__send__(k) }
    end
  end

  hash = hash.merge(locals || {})

  if content
    hash[:content] = content.call.to_s  # rescue nil ?
  end

  hash
end
make_object(scope, locals=nil) click to toggle source

Convert data into an object.

@param [Object,Binding,Hash,Array] data

The data source used for evaluation.

@return [Object] The data and yield block converted to an Object.

# File lib/malt/engines/abstract.rb, line 225
def make_object(scope, locals=nil)
  locals ||= {}

  case scope
  when nil
    hash = locals.to_hash.dup
    if hash.empty?
      Object.new
    else
      vars, vals = [], []
      hash.each_pair do |k,v|
        vars << k; vals << v
      end
      Struct.new(*vars).new(*vals)
    end
  when Binding
    Class.new(::BasicObject){
      define_method(:method_missing) do |s, *a|
        if locals.key?(s)
          locals[s]
        elsif locals.key?(s.to_s)
          locals[s.to_s]
        else
          scope.eval(s.to_s)
        end
      end
    }.new
  when Struct
    vars, vals = [], []
    scope.each_pair do |k,v|
      vars << k; vals << v
    end
    locals.each_pair do |k,v|
      vars << k; vals << v
    end
    Struct.new(*vars).new(*vals)
  else
    if scope.respond_to?(:to_hash)
      hash = scope.to_hash.merge(locals.to_hash)
      if hash.empty?
        Object.new
      else
        vars, vals = [], []
        hash.each_pair do |k,v|
          vars << k; vals << v
        end
        Struct.new(*vars).new(*vals)
      end
    else
      Class.new(::BasicObject){
        define_method(:method_missing) do |s, *a, &b|
          if locals.key?(s)
            locals[s]
          elsif locals.key?(s.to_s)
            locals[s.to_s]
          else
            scope.__send__(s.to_s, *a, &b)
          end
        end
      }.new
    end
  end
end
make_ready(scope, locals=nil, &content) click to toggle source

Take `scope` and `locals` data sources are return them as object and locals hash.

@param [Object,Binding] scope

@param [Hash] locals

@return [Array<Object,Hash>] Two element array of scope object and data hash.

# File lib/malt/engines/abstract.rb, line 134
def make_ready(scope, locals=nil, &content)
  locals ||= {}

  case scope
  when Binding
    vars   = scope.eval("local_variables")
    vals   = scope.eval("[#{vars.join(',')}]")
    locals = locals.merge(Hash[*vars.zip(vals).flatten])
    scope  = scope.eval("self")
  end

  if scope.respond_to?(:to_struct)
    locals = locals.merge(scope.to_struct.to_h)
    scope  = Object.new
  end

  if scope.respond_to?(:to_hash)
    locals = locals.merge(scope.to_hash)
    scope  = Object.new
  end

  scope ||= Object.new

  locals[:content] = content.call if content

  return scope, locals
end
parameters(params, *names) click to toggle source

Helper method to get paramters.

# File lib/malt/engines/abstract.rb, line 354
def parameters(params, *names)
  pvals = names.map do |name|
    params[name.to_sym] || settings[name.to_sym]
  end

  if names.size == 1
    return pvals.first
  else
    return *pvals
  end
end
require_engine() click to toggle source

Override this to load template engine library and prepare is for geeral usage.

# File lib/malt/engines/abstract.rb, line 116
def require_engine
end
require_library(path) click to toggle source

Require template library.

# File lib/malt/engines/abstract.rb, line 120
def require_library(path)
  require(path)
end