Class: Mustache

Inherits:
Object
  • Object
show all
Defined in:
lib/mustache.rb,
lib/mustache/utils.rb,
lib/mustache/parser.rb,
lib/mustache/context.rb,
lib/mustache/version.rb,
lib/mustache/settings.rb,
lib/mustache/template.rb,
lib/mustache/generator.rb,
lib/mustache/enumerable.rb,
lib/mustache/context_miss.rb

Overview

Settings which can be configured for all view classes, a single view class, or a single Mustache instance.

Defined Under Namespace

Modules: Utils Classes: Context, ContextLevelViolation, ContextMiss, Generator, Parser, Template

Constant Summary collapse

VERSION =
'1.1.3'
Enumerable =
Module.new
MethodBlacklist =
["allocate", "attached_object", "superclass", "subclasses", "new", "autoload?", "autoload",
"included_modules", "include?", "set_temporary_name", "ancestors", "attr", "attr_reader", "attr_writer",
"attr_accessor", "public_instance_method", "instance_methods", "public_instance_methods",
"protected_instance_methods", "private_instance_methods", "undefined_instance_methods", "freeze", "const_get",
"constants", "const_missing", "const_defined?", "const_set", "const_source_location", "remove_class_variable",
"class_variable_get", "class_variables", "private_constant", "class_variable_set", "class_variable_defined?",
"public_constant", "include", "deprecate_constant", "singleton_class?", "prepend", "refinements", "define_method",
"module_exec", "class_exec", "module_eval", "class_eval", "remove_method", "undef_method", "alias_method",
"method_defined?", "public_method_defined?", "private_method_defined?", "protected_method_defined?",
"public_class_method", "private_class_method", "instance_method", "singleton_class", "dup", "itself", "methods",
"singleton_methods", "protected_methods", "private_methods", "public_methods", "instance_variables",
"instance_variable_get", "instance_variable_set", "instance_variable_defined?", "remove_instance_variable",
"instance_of?", "kind_of?", "is_a?", "display", "public_send", "extend", "clone", "class", "frozen?", "tap",
"then", "yield_self", "respond_to?", "method", "public_method", "singleton_method", "define_singleton_method",
"hash", "object_id", "send", "enum_for", "__send__", "instance_eval", "instance_exec", "__id__"]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Mustache

Initialize a new Mustache instance.

Parameters:

  • options (Hash) (defaults to: {})

    An options hash

Options Hash (options):

  • template_path (String)
  • template_extension (String)
  • template_file (String)
  • template (String)
  • view_namespace (String)
  • view_path (String)


86
87
88
89
90
# File 'lib/mustache.rb', line 86

def initialize(options = {})
  @options = options
  
  initialize_settings
end

Class Method Details

.classify(underscored) ⇒ Object

template_partial => TemplatePartial template/partial => Template::Partial



287
288
289
# File 'lib/mustache.rb', line 287

def self.classify(underscored)
  Mustache::Utils::String.new(underscored).classify
end

.compiled?Boolean

Has this template already been compiled? Compilation is somewhat expensive so it may be useful to check this before attempting it.

Returns:

  • (Boolean)


280
281
282
# File 'lib/mustache.rb', line 280

def self.compiled?
  @template.is_a? Template
end

.const_from_file(name) ⇒ Object



268
269
270
271
272
273
274
275
276
# File 'lib/mustache.rb', line 268

def self.const_from_file name
  file_name = underscore(name)
  file_path = "#{view_path}/#{file_name}.rb"

  return Mustache unless File.exist?(file_path)

  require file_path.chomp('.rb')
  rescued_const_get(name)
end

.context_access_security_levelObject

What object methods could be accessed from the template? This level determines the security restrictions for method access to protect against unsafe reflection Possible values are integers from 1 to 5:

1 - All methods allowed (use only with trusted templates) 2 - Reflection-related methods are blacklisted (default) 3 - All inherited or reflection-related methods are prohibited 4 - Access allowed only for Hash elements 5 - Access allowed only for Hash elements, only numbers, strings, hashes and functions allowed



237
238
239
# File 'lib/mustache/settings.rb', line 237

def self.context_access_security_level
  @context_access_security_level
end

.context_access_security_level=(integer) ⇒ Object



241
242
243
# File 'lib/mustache/settings.rb', line 241

def self.context_access_security_level=(integer)
  @context_access_security_level = integer
end

.inheritable_config_for(attr_name, default) ⇒ Object

Return the value of the configuration setting on the superclass, or return the default.

Parameters:

  • attr_name (Symbol)

    Name of the attribute. It should match the instance variable.

  • default (Object)

    Default value to use if the superclass does not respond.

Returns:

  • Inherited or default configuration setting.



321
322
323
# File 'lib/mustache.rb', line 321

def self.inheritable_config_for(attr_name, default)
  superclass.respond_to?(attr_name) ? superclass.send(attr_name) : default
end

.inherited(subclass) ⇒ Object



27
28
29
# File 'lib/mustache/settings.rb', line 27

def self.inherited(subclass)
  subclass.initialize_settings
end

.initialize_settingsObject



15
16
17
18
19
20
21
22
23
# File 'lib/mustache/settings.rb', line 15

def self.initialize_settings
  @template = nil
  @template_path = nil
  @template_extension = nil
  @template_name = nil
  @template_file = nil
  @raise_on_context_miss = nil
  @context_access_security_level = 2
end

.partial(name) ⇒ Object

Given a name, attempts to read a file and return the contents as a string. The file is not rendered, so it might contain {mustaches}.

Call render if you need to process it.



182
183
184
# File 'lib/mustache.rb', line 182

def self.partial(name)
  self.new.partial(name)
end

.raise_on_context_miss=(boolean) ⇒ Object



210
211
212
# File 'lib/mustache/settings.rb', line 210

def self.raise_on_context_miss=(boolean)
  @raise_on_context_miss = boolean
end

.raise_on_context_miss?Boolean

Should an exception be raised when we cannot find a corresponding method or key in the current context? By default this is false to emulate ctemplate's behavior, but it may be useful to enable when debugging or developing.

If set to true and there is a context miss, Mustache::ContextMiss will be raised.

Returns:

  • (Boolean)


206
207
208
# File 'lib/mustache/settings.rb', line 206

def self.raise_on_context_miss?
  @raise_on_context_miss
end

.render(*args) ⇒ Object

Instantiates an instance of this class and calls render with the passed args.

Returns:

  • A rendered String version of a template.



96
97
98
# File 'lib/mustache.rb', line 96

def self.render(*args)
  new.render(*args)
end

.render_file(name, context = {}) ⇒ Object

Given a file name and an optional context, attempts to load and render the file as a template.



167
168
169
# File 'lib/mustache.rb', line 167

def self.render_file(name, context = {})
  render(partial(name), context)
end

.rescued_const_get(name) ⇒ Object



262
263
264
265
266
# File 'lib/mustache.rb', line 262

def self.rescued_const_get name
  const_get(name, true) || Mustache
rescue NameError
  nil
end

.setup_path(path) ⇒ Object

The template path informs your Mustache view where to look for its corresponding template. It is an array of paths, by default containing one entry: the current directory (".") When setting up from a string, use path delimiters to create a search path When the template_file is requested, a search is done to find the file in the path, this is then stored as the name.

A class named Stat with a template_path of "app/templates" will look for "app/templates/stat.mustache"



45
46
47
48
# File 'lib/mustache/settings.rb', line 45

def self.setup_path path
  path = path.split(File::PATH_SEPARATOR) if path.is_a? String
  path.map{|p| File.expand_path(p)}
end

.templateObject

The template is the actual string Mustache uses as its template. There is a bit of magic here: what we get back is actually a Mustache::Template object, but you can still safely use template= with a string.



170
171
172
# File 'lib/mustache/settings.rb', line 170

def self.template
  @template ||= templateify(File.read(template_file))
end

.template=(template) ⇒ Object



174
175
176
# File 'lib/mustache/settings.rb', line 174

def self.template=(template)
  @template = templateify(template)
end

.template_extensionObject

A Mustache template's default extension is 'mustache', but this can be changed.



82
83
84
# File 'lib/mustache/settings.rb', line 82

def self.template_extension
  @template_extension ||= inheritable_config_for :template_extension, 'mustache'
end

.template_extension=(template_extension) ⇒ Object



86
87
88
89
# File 'lib/mustache/settings.rb', line 86

def self.template_extension=(template_extension)
  @template_extension = template_extension
  @template = nil
end

.template_fileObject

The template file is the absolute path of the file Mustache will use as its template. By default it's ./class_name.mustache



142
143
144
# File 'lib/mustache/settings.rb', line 142

def self.template_file
  @template_file || path.map{|p| "#{p}/#{template_name}.#{template_extension}" }.find{|tf| File.readable? tf}
end

.template_file=(tf) ⇒ Object



146
147
148
149
# File 'lib/mustache/settings.rb', line 146

def self.template_file=(tf)
  @template_file = tf
  @template = nil
end

.template_nameObject

The template name is the Mustache template file without any extension or other information. Defaults to class_name.

You may want to change this if your class is named Stat but you want to re-use another template.

class Stat
self.template_name = "graphs" # use graphs.mustache
end


115
116
117
# File 'lib/mustache/settings.rb', line 115

def self.template_name
  @template_name || underscore
end

.template_name=(template_name) ⇒ Object



119
120
121
122
# File 'lib/mustache/settings.rb', line 119

def self.template_name=(template_name)
  @template_name = template_name
  @template = nil
end

.template_pathObject Also known as: path



50
51
52
# File 'lib/mustache/settings.rb', line 50

def self.template_path
  @template_path ||= setup_path(inheritable_config_for(:template_path, '.'))
end

.template_path=(path) ⇒ Object Also known as: path=



54
55
56
57
# File 'lib/mustache/settings.rb', line 54

def self.template_path=(path)
  @template_path = setup_path(path)
  @template = nil
end

.templateify(obj, options = {}) ⇒ Object

Parameters:

  • obj (Template, String)

    Turns obj into a template

  • options (Hash) (defaults to: {})

    Options for template creation



302
303
304
# File 'lib/mustache.rb', line 302

def self.templateify(obj, options = {})
  obj.is_a?(Template) ? obj : Template.new(obj, options)
end

.underscore(classified = name) ⇒ Object

TemplatePartial => template_partial Template::Partial => template/partial Takes a string but defaults to using the current class' name.



294
295
296
297
298
# File 'lib/mustache.rb', line 294

def self.underscore(classified = name)
  classified = superclass.name if classified.to_s.empty?

  Mustache::Utils::String.new(classified).underscore(view_namespace)
end

.view_class(name) ⇒ Object

When given a symbol or string representing a class, will try to produce an appropriate view class.

Examples:

Mustache.view_namespace = Hurl::Views
Mustache.view_class(:Partial) # => Hurl::Views::Partial


248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/mustache.rb', line 248

def self.view_class(name)
  name = classify(name.to_s)

  # Emptiness begets emptiness.
  return Mustache if name.to_s.empty?

  name = "#{view_namespace}::#{name}"
  const = rescued_const_get(name)

  return const if const

  const_from_file(name)
end

.view_namespaceObject

The constant under which Mustache will look for views when autoloading. By default the view namespace is Object, but it might be nice to set it to something like Hurl::Views if your app's main namespace is Hurl.



263
264
265
# File 'lib/mustache/settings.rb', line 263

def self.view_namespace
  @view_namespace ||= inheritable_config_for(:view_namespace, Object)
end

.view_namespace=(namespace) ⇒ Object



267
268
269
# File 'lib/mustache/settings.rb', line 267

def self.view_namespace=(namespace)
  @view_namespace = namespace
end

.view_pathObject

Mustache searches the view path for .rb files to require when asked to find a view class. Defaults to "."



279
280
281
# File 'lib/mustache/settings.rb', line 279

def self.view_path
  @view_path ||= inheritable_config_for(:view_path, '.')
end

.view_path=(path) ⇒ Object



283
284
285
# File 'lib/mustache/settings.rb', line 283

def self.view_path=(path)
  @view_path = path
end

Instance Method Details

#[](key) ⇒ Object

Context accessors.

Examples:

Context accessors

view = Mustache.new
view[:name] = "Jon"
view.template = "Hi, {{name}}!"
view.render # => "Hi, Jon!"


150
151
152
# File 'lib/mustache.rb', line 150

def [](key)
  context[key.to_sym]
end

#[]=(key, value) ⇒ Object



154
155
156
# File 'lib/mustache.rb', line 154

def []=(key, value)
  context[key.to_sym] = value
end

#compiled?Boolean

Has this instance or its class already compiled a template?

Returns:

  • (Boolean)


234
235
236
# File 'lib/mustache.rb', line 234

def compiled?
  (@template && @template.is_a?(Template)) || self.class.compiled?
end

#contextObject

A helper method which gives access to the context at a given time. Kind of a hack for now, but useful when you're in an iterating section and want access to the hash currently being iterated over.



161
162
163
# File 'lib/mustache.rb', line 161

def context
  @context ||= Context.new(self)
end

#context_access_security_levelObject

Instance level version of Mustache.context_access_security_level



246
247
248
# File 'lib/mustache/settings.rb', line 246

def context_access_security_level
  self.class.context_access_security_level || @context_access_security_level
end

#context_access_security_level=(integer) ⇒ Object



250
251
252
# File 'lib/mustache/settings.rb', line 250

def context_access_security_level=(integer)
  @context_access_security_level = integer
end

#escape(value) ⇒ String

Override this to provide custom escaping. By default it uses CGI.escapeHTML.

Examples:

Overriding #escape

class PersonView < Mustache
  def escape(value)
    my_html_escape_method(value.to_s)
  end
end

Parameters:

  • value (Object)

    Value to escape.

Returns:

  • (String)

    Escaped content.



209
210
211
# File 'lib/mustache.rb', line 209

def escape(value)
  self.escapeHTML(value.to_s)
end

#escapeHTML(str) ⇒ String

Deprecated.

Use #escape instead.

Note that #escape can receive any kind of object. If your override logic is expecting a string, you will have to call to_s on it yourself.

Override this to provide custom escaping.

Examples:

Overriding #escapeHTML

class PersonView < Mustache
  def escapeHTML(str)
    my_html_escape_method(str)
  end
end

Parameters:

  • str (String)

    String to escape.

Returns:

  • (String)

    Escaped HTML.



229
230
231
# File 'lib/mustache.rb', line 229

def escapeHTML(str)
  CGI.escapeHTML(str)
end

#initialize_settingsObject



5
6
7
8
9
10
11
12
13
# File 'lib/mustache/settings.rb', line 5

def initialize_settings
  @template = nil
  @template_path = nil
  @template_extension = nil
  @template_name = nil
  @template_file = nil
  @raise_on_context_miss = nil
  @context_access_security_level = 2
end

#partial(name) ⇒ Object

Override this in your subclass if you want to do fun things like reading templates from a database. It will be rendered by the context, so all you need to do is return a string.

Raises:

  • (RuntimeError)


189
190
191
192
193
194
195
# File 'lib/mustache.rb', line 189

def partial(name)
  partialpath = template_path.map{|p| "#{p}/#{name}.#{template_extension}" }.find{|pf| File.readable? pf}

  raise RuntimeError.new("Can't find partial #{name}") if not partialpath and raise_on_context_miss?

  partialpath ? File.read(partialpath) : ""
end

#raise_on_context_miss=(boolean) ⇒ Object



219
220
221
# File 'lib/mustache/settings.rb', line 219

def raise_on_context_miss=(boolean)
  @raise_on_context_miss = boolean
end

#raise_on_context_miss?Boolean

Instance level version of Mustache.raise_on_context_miss?

Returns:

  • (Boolean)


215
216
217
# File 'lib/mustache/settings.rb', line 215

def raise_on_context_miss?
  self.class.raise_on_context_miss? || @raise_on_context_miss
end

#render(data = template, ctx = {}) ⇒ String

Parses our fancy pants template file and returns normal file with all special {tags} and Mustache.{{#sections}replaced{/sections}.

Examples:

Render view

@view.render("Hi {{thing}}!", :thing => :world)

Set view template and then render

View.template = "Hi {{thing}}!"
@view = View.new
@view.render(:thing => :world)

Parameters:

  • data (String, Hash) (defaults to: template)

    A String template or a Hash context. If a Hash is given, we'll try to figure out the template from the class.

  • ctx (Hash) (defaults to: {})

    A Hash context if data is a String template.

Returns:

  • (String)

    Returns a rendered version of a template.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/mustache.rb', line 116

def render(data = template, ctx = {})
  case data
  when Hash
    ctx = data
  when Symbol
    self.template_name = data
  end

  tpl = case data
  when Hash
    templateify(template)
  when Symbol
    templateify(template)
  else
    templateify(data)
  end

  return tpl.render(context) if ctx == {}

  begin
    context.push(ctx)
    tpl.render(context)
  ensure
    context.pop
  end
end

#render_file(name, context = {}) ⇒ Object

Given a file name and an optional context, attempts to load and render the file as a template.



173
174
175
# File 'lib/mustache.rb', line 173

def render_file(name, context = {})
  self.class.render_file(name, context)
end

#templateObject

The template can be set at the instance level.



179
180
181
182
183
184
185
186
187
188
# File 'lib/mustache/settings.rb', line 179

def template
  return @template if @template

  # If they sent any instance-level options use that instead of the class's.
  if @template_path || @template_extension || @template_name || @template_file
    @template = templateify(File.read(template_file))
  else
    @template = self.class.template
  end
end

#template=(template) ⇒ Object



190
191
192
# File 'lib/mustache/settings.rb', line 190

def template=(template)
  @template = templateify(template)
end

#template_extensionObject



91
92
93
# File 'lib/mustache/settings.rb', line 91

def template_extension
  @template_extension ||= self.class.template_extension
end

#template_extension=(template_extension) ⇒ Object



95
96
97
98
# File 'lib/mustache/settings.rb', line 95

def template_extension=(template_extension)
  @template_extension = template_extension
  @template = nil
end

#template_fileObject



151
152
153
# File 'lib/mustache/settings.rb', line 151

def template_file
  @template_file || path.map{|p| "#{p}/#{template_name}.#{template_extension}" }.find{|tf| File.readable? tf}
end

#template_file=(tf) ⇒ Object



155
156
157
158
# File 'lib/mustache/settings.rb', line 155

def template_file=(tf)
  @template_file = tf
  @template = nil
end

#template_nameObject



124
125
126
# File 'lib/mustache/settings.rb', line 124

def template_name
  @template_name ||= self.class.template_name
end

#template_name=(template_name) ⇒ Object



128
129
130
131
# File 'lib/mustache/settings.rb', line 128

def template_name=(template_name)
  @template_name = template_name
  @template = nil
end

#template_pathObject Also known as: path



59
60
61
# File 'lib/mustache/settings.rb', line 59

def template_path
  @template_path ||= self.class.template_path
end

#template_path=(path) ⇒ Object



65
66
67
68
# File 'lib/mustache/settings.rb', line 65

def template_path=(path)
  @template_path = self.class.setup_path(path)
  @template = nil
end