Class: Tap::Support::Templater

Inherits:
OpenStruct
  • Object
show all
Includes:
Utils
Defined in:
lib/tap/support/templater.rb

Overview

Templater is a convenience class for creating ERB templates. As a subclass of OpenStruct, attributes can be assigned/unassigned directly. When the template is built, all the method of Templater (and hence all the assigned attributes) are available.

t = Templater.new( "key: <%= value %>")
t.value = "default"
t.build                 # => "key: default"

t.value = "another"
t.build                 # => "key: another"

Templater includes the Templater::Utils utility methods.

ERB Redirection

Templater hooks into the ERB templating mechanism by providing itself as the ERB output target (_erbout). ERB concatenates each line of an ERB template to _erbout, as can be seen here:

e = ERB.new("<%= 1 + 2 %>")
e.src                   # => "_erbout = ''; _erbout.concat(( 1 + 2 ).to_s); _erbout"

By setting itself as _erbout, instances of Templater can redirect output to a temporary target and perform string transformations.

For example, redirection allows indentation of nested content:

template = %Q{
# Un-nested content
<% redirect do |target| %>
# Nested content
<% module_nest("Nesting::Module") { target } %>
<% end %>
}

t = Templater.new(template)
t.build
# => %Q{
# # Un-nested content
# module Nesting
#   module Module
#     # Nested content
#     
#   end
# end}

Defined Under Namespace

Modules: Utils

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

#comment, #module_nest, #nest, #yamlize

Constructor Details

#initialize(template, attributes = {}) ⇒ Templater

Initialized a new Templater. An ERB or String may be provided as the template. If a String is provided, it will be used to initialize an ERB with a trim_mode of “<>”.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/tap/support/templater.rb', line 133

def initialize(template, attributes={})
  @template = case template
  when ERB
    # matching w/wo the coding effectively checks @src
    # across ruby versions (encoding appears in 1.9)
    if template.instance_variable_get(:@src) !~ /^(#coding:US-ASCII\n)?_erbout =/
      raise ArgumentError, "Templater does not work with ERB templates where eoutvar != '_erbout'"
    end
    template
  when String then ERB.new(template, nil, "<>")
  else raise ArgumentError, "cannot convert #{template.class} into an ERB template"
  end
  
  src = @template.instance_variable_get(:@src)
  @template.instance_variable_set(:@src, "self." + src) 

  super(attributes)
end

Class Method Details

.build(template, attributes = {}) ⇒ Object



123
124
125
# File 'lib/tap/support/templater.rb', line 123

def build(template,  attributes={})
  new(template, attributes).build
end

Instance Method Details

#_erboutObject

Returns self (not the underlying erbout storage that actually receives the output lines). In the ERB context, this method directs erb outputs to Templater#concat and into the redirect mechanism.



155
156
157
# File 'lib/tap/support/templater.rb', line 155

def _erbout
  self
end

#_erbout=(input) ⇒ Object

Sets the underlying erbout storage to input.



160
161
162
# File 'lib/tap/support/templater.rb', line 160

def _erbout=(input)
  @_erbout = input
end

#build(attrs = {}) ⇒ Object

Build the template. All methods of self will be accessible in the template.



183
184
185
186
187
188
189
190
# File 'lib/tap/support/templater.rb', line 183

def build(attrs={})
  attrs.each_pair do |key, value|
    send("#{key}=", value)
  end
  
  @template.result(binding)
  @_erbout
end

#concat(input) ⇒ Object

Concatenates the specified input to the underlying erbout storage.



177
178
179
# File 'lib/tap/support/templater.rb', line 177

def concat(input)
  @_erbout << input
end

#redirectObject

Redirects output of erb to the redirected_erbout string for the duration of the block. When redirect completes, the redirected_erbout is concatenated to the main erbout storage.



168
169
170
171
172
173
174
# File 'lib/tap/support/templater.rb', line 168

def redirect # :yields: redirected_erbout
  current = @_erbout
  @_erbout = ""
  result = yield(@_erbout)
  @_erbout = current
  concat(result)
end