Parent

Inversion::Template

The main template class. Instances of this class are created by parsing template source and combining the resulting node tree with a set of attributes that can be used to populate it when rendered.


Add the mixin to Template

Public Class Methods

configure( config ) click to toggle source

Configure the templating system.

# File lib/inversion/template.rb, line 64
def self::configure( config )
        Inversion.log.debug "Merging config %p with current config %p" % [ config, self.config ]
        self.config = self.config.merge( config )
end
load( path, parsestate=nil, opts={} ) click to toggle source

Read a template object from the specified path.

# File lib/inversion/template.rb, line 71
def self::load( path, parsestate=nil, opts={} )

        # Shift the options hash over if there isn't a parse state
        if parsestate.is_a?( Hash )
                opts = parsestate
                parsestate = nil
        end

        tmpl = nil
        path = Pathname( path )
        template_paths = Array( self.config[:template_paths] ) + [ Dir.pwd ]

        # Unrestricted template location.
        if path.absolute?
                tmpl = path

        # Template files searched under paths specified in 'template_paths', then
        # the current working directory. First match wins.
        else
                tmpl = template_paths.collect {|dir| Pathname(dir) + path }.find do |fullpath|
                        fullpath.exist?
                end

                raise RuntimeError, "Unable to find template %p within configured paths %p" %
                        [ path.to_s, template_paths ] if tmpl.nil?
        end

        # We trust files read from disk
        source = tmpl.read
        source.untaint

        # Load the instance and set the path to the source
        template = self.new( source, parsestate, opts )
        template.source_file = tmpl

        return template
end
new( source, parsestate=nil, opts={} ) click to toggle source

Create a new Inversion:Template with the given source.

# File lib/inversion/template.rb, line 111
def initialize( source, parsestate=nil, opts={} )
        if parsestate.is_a?( Hash )
                self.log.debug "Shifting template options: %p" % [ parsestate ]
                opts = parsestate
                parsestate = nil
        else
                self.log.debug "Parse state is: %p" % [ parsestate ]
        end

        @source       = source
        @parser       = Inversion::Parser.new( self, opts )
        @node_tree    = [] # Parser expects this to always be an Array
        @init_options = opts
        @options      = nil
        @attributes   = {}
        @source_file  = nil
        @created_at   = Time.now

        self.parse( source, parsestate )
end

Public Instance Methods

changed?() click to toggle source

Returns true if the template was loaded from a file and the file's mtime is after the time the template was created.

# File lib/inversion/template.rb, line 166
def changed?
        return false unless file = self.source_file
        return ( file.mtime > @created_at )
end
inspect() click to toggle source

Return a human-readable representation of the template object suitable for debugging.

# File lib/inversion/template.rb, line 195
def inspect
        return "#<%s:%08x (loaded from %s) attributes: %p, node_tree: %p, options: %p>" % [
                self.class.name,
                self.object_id / 2,
                self.source_file ? self.source_file : "memory",
                self.attributes,
                self.node_tree.map(&:as_comment_body),
                self.options,
        ]
end
reload() click to toggle source

If the template was loaded from a file, reload and reparse it from the same file.

# File lib/inversion/template.rb, line 154
def reload
        file = self.source_file or
                raise Inversion::Error, "template was not loaded from a file" 

        self.log.debug "Reloading from %s" % [ file ]
        source = file.read
        self.parse( source )
end
render( parentstate=nil, &block ) click to toggle source

Render the template, optionally passing a render state (if, for example, the template is being rendered inside another template).

# File lib/inversion/template.rb, line 174
def render( parentstate=nil, &block )
        self.log.info "rendering template 0x%08x" % [ self.object_id/2 ]
        state = Inversion::RenderState.new( parentstate, self.attributes, self.options, &block )

        # Pre-render hook
        self.walk_tree {|node| node.before_rendering(state) }

        # self.log.debug "  rendering node tree: %p" % [ @node_tree ]
        self.walk_tree {|node| state << node }

        # Post-render hook
        self.walk_tree {|node| node.after_rendering(state) }

        self.log.info "  done rendering template 0x%08x" % [ self.object_id/2 ]
        return state.to_s
end
Also aliased as: to_s
to_s( parentstate=nil, &block ) click to toggle source
Alias for: render

Protected Instance Methods

add_attributes_from_node( node ) click to toggle source

Add attributes for the given node's identifiers.

# File lib/inversion/template.rb, line 256
def add_attributes_from_node( node )
        if node.respond_to?( :identifiers )
                node.identifiers.each do |id|
                        next if @attributes.key?( id.to_sym )
                        @attributes[ id.to_sym ] = nil
                end
        end
end
define_attribute_accessors() click to toggle source

Search for identifiers in the template's node tree and declare an accessor for each one that's found.

# File lib/inversion/template.rb, line 244
def define_attribute_accessors
        self.walk_tree do |node|
                self.add_attributes_from_node( node )
        end

        self.attributes.each do |key, _|
                self.install_accessors( key )
        end
end
install_accessors( key ) click to toggle source

Install reader and writer methods for the attribute associated with the specified key.

# File lib/inversion/template.rb, line 267
def install_accessors( key )
        reader, writer = self.make_attribute_accessors( key )

        self.singleton_class.send( :define_method, key, &reader )
        self.singleton_class.send( :define_method, "#{key}=", &writer )
end
make_attribute_accessors( key ) click to toggle source

Make method bodies

# File lib/inversion/template.rb, line 276
def make_attribute_accessors( key )
        key = key.to_sym
        reader = lambda { self.attributes[key] }
        writer = lambda {|newval| self.attributes[key] = newval }

        return reader, writer
end
method_missing( sym, *args, &block ) click to toggle source

Proxy method: handle attribute readers/writers for attributes that aren't yet defined.

# File lib/inversion/template.rb, line 213
def method_missing( sym, *args, &block )
        return super unless sym.to_s =~ /^([a-z]\w+)=?$/
        attribute = $1
        self.install_accessors( attribute )

        # Call the new method via #method to avoid a method_missing loop.
        return self.method( sym ).call( *args, &block )
end
parse( source, parsestate=nil ) click to toggle source

Parse the given source into the template node tree.

# File lib/inversion/template.rb, line 224
def parse( source, parsestate=nil )
        @options = self.class.config.merge( @init_options )
        @attributes.clear
        @node_tree = @parser.parse( source, parsestate )
        @source = source

        self.define_attribute_accessors
end
walk_tree( nodes=@node_tree, &block ) click to toggle source

Walk the template's node tree, yielding each node in turn to the given block.

# File lib/inversion/template.rb, line 235
def walk_tree( nodes=@node_tree, &block )
        nodes.each do |node|
                yield( node )
        end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.