Class: Inversion::Template::BeginTag

Inherits:
Tag
  • Object
show all
Includes:
ContainerTag
Defined in:
lib/inversion/template/begintag.rb

Overview

Inversion ‘begin’ tag.

This tag causes a section of the template to be rendered only if no exceptions are raised while it’s being rendered. If an exception is raised, it is checked against any ‘rescue’ blocks, and the first one with a matching exception is rendered instead. If no ‘rescue’ block is found, the exception is handled by the configured exception behavior for the template, and the resulting replaces the block.

Syntax

<?begin ?><?call employees.length ?><?end?>

<?begin ?>
    <?for employee in employees.all ?>
        <?attr employee.name ?> --> <?attr employee.title ?>
    <?end for?>
<?rescue DatabaseError => err ?>
    Oh no!! I can't talk to the database for some reason.  The
    error was as follows:
    <pre>
        <?attr err.message ?>
    </pre>
<?end?>

Constant Summary

Constants inherited from Tag

Tag::TAG_PLUGIN_PATTERN

Instance Attribute Summary collapse

Attributes included from ContainerTag

#subnodes

Attributes inherited from Tag

#body

Attributes inherited from Node

#colnum, #linenum

Instance Method Summary collapse

Methods included from ContainerTag

#is_container?, #render_subnodes

Methods inherited from Tag

#as_comment_body, create, #derivatives, inherited, load, load_all, #tagname, types, #types

Methods included from MethodUtilities

#singleton_attr_accessor, #singleton_attr_reader, #singleton_attr_writer

Methods included from AbstractClass

included

Methods included from AbstractClass::ClassMethods

#inherited, #pure_virtual

Methods inherited from Node

#after_appending, #after_rendering, #as_comment_body, #before_appending, #before_rendering, #is_container?, #location

Constructor Details

#initialize(body = '', linenum = nil, colnum = nil) ⇒ BeginTag

Initialize a new BeginTag.



40
41
42
43
# File 'lib/inversion/template/begintag.rb', line 40

def initialize( body='', linenum=nil, colnum=nil ) # :notnew:
	super
	@rescue_clauses = [] # [ [RuntimeError, ArgumentError], [subnodes] ]
end

Instance Attribute Details

#rescue_clausesObject (readonly)

The tuples of rescue clauses handled by the begin



51
52
53
# File 'lib/inversion/template/begintag.rb', line 51

def rescue_clauses
  @rescue_clauses
end

Instance Method Details

#<<(subnode) ⇒ Object

Override the append operator to separate out RescueTags and the nodes that follow them.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/inversion/template/begintag.rb', line 56

def <<( subnode )
	case

	# If this node is a <?rescue?>, add a container for the subnodes that belong to it
	# and the list of exception types that it rescues
	when subnode.is_a?( Inversion::Template::RescueTag )
		@rescue_clauses << [ subnode.exception_types, [] ]

	# If there's already at least one rescue clause in effect, add any subnodes to
	# the last one
	when !@rescue_clauses.empty?
		@rescue_clauses.last[1] << subnode

	# Append nodes in the begin, but before any rescue to the begin tag
	else
		super
	end

	return self
end

#handle_exception(state, node, exception) ⇒ Object

The replacement exception-handler provided to RenderState.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/inversion/template/begintag.rb', line 100

def handle_exception( state, node, exception )
	self.log.debug "Handling %p raised by %p: %s" % [ exception.class, node, exception.message ]
	state.destination.clear

	self.rescue_clauses.each do |errclasses, nodes|
		self.log.debug "  considering rescue clause: %p -> %p" % [ errclasses, nodes ]
		if errclasses.any? {|eclass| eclass === exception }
			self.log.debug "  rescued by a clause for %p" % [ errclasses ]
			nodes.each {|innernode| state << innernode }
			throw :stop_rendering
		end
	end

	# Use the default error handler
	self.log.debug "  no rescue clause for a %p: falling back to the default error handler" %
		[ exception.class ]
	state.destination << state.default_error_handler( state, node, exception )
	throw :stop_rendering
end

#render(state) ⇒ Object

Render the tag’s contents if the condition is true, or any else or elsif sections if the condition isn’t true.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/inversion/template/begintag.rb', line 80

def render( state )
	output = []

	errhandler = self.method( :handle_exception )
	state.with_destination( output ) do
		state.with_error_handler( errhandler ) do
			catch( :stop_rendering ) do
				super
			end
			self.log.debug "  leaving the error-handler block"
		end
		self.log.debug "  leaving the overridden output block"
	end

	self.log.debug "Rendered begin section as: %p" % [ output ]
	return output
end