Class: Haml::Engine

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Util
Defined in:
lib/haml/engine.rb

Overview

This is the frontend for using Haml programmatically. It can be directly used by the user by creating a new instance and calling #render to render the template. For example:

template = File.read('templates/really_cool_template.haml')
haml_engine = Haml::Engine.new(template)
output = haml_engine.render
puts output

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Methods included from Util

#av_template_class, #balance, #caller_info, #check_encoding, #check_haml_encoding, #contains_interpolation?, #def_static_method, #handle_interpolation, #html_safe, #human_indentation, #inspect_obj, #powerset, #rails_xss_safe?, #silence_warnings, #static_method_name, #unescape_interpolation

Constructor Details

- (Engine) initialize(template, options = {})

Precompiles the Haml template.

Parameters:

Raises:

  • (Haml::Error)

    if there’s a Haml syntax error in the template



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/haml/engine.rb', line 54

def initialize(template, options = {})
  @options = Options.new(options)

  @template = check_haml_encoding(template) do |msg, line|
    raise Haml::Error.new(msg, line)
  end

  initialize_encoding options[:encoding]

  @parser   = @options.parser_class.new(@template, @options)
  @compiler = @options.compiler_class.new(@options)

  @compiler.compile(@parser.parse)
end

Instance Attribute Details

- compiler

Returns the value of attribute compiler



38
39
40
# File 'lib/haml/engine.rb', line 38

def compiler
  @compiler
end

- (String) indentation

The indentation used in the Haml document, or nil if the indentation is ambiguous (for example, for a single-level document).

Returns:

  • (String)


36
37
38
# File 'lib/haml/engine.rb', line 36

def indentation
  @indentation
end

- options

The Haml::Options instance. See the Haml options documentation.

Returns:

  • Haml::Options



29
30
31
# File 'lib/haml/engine.rb', line 29

def options
  @options
end

- parser

Returns the value of attribute parser



39
40
41
# File 'lib/haml/engine.rb', line 39

def parser
  @parser
end

Instance Method Details

- def_method(object, name, *local_names)

Defines a method on object with the given name that renders the template and returns the result as a string.

If object is a class or module, the method will instead by defined as an instance method. For example:

t = Time.now
Haml::Engine.new("%p\n  Today's date is\n  .date= self.to_s").def_method(t, :render)
t.render #=> "<p>\n  Today's date is\n  <div class='date'>Fri Nov 23 18:28:29 -0800 2007</div>\n</p>\n"

Haml::Engine.new(".upcased= upcase").def_method(String, :upcased_div)
"foobar".upcased_div #=> "<div class='upcased'>FOOBAR</div>\n"

The first argument of the defined method is a hash of local variable names to values. However, due to an unfortunate Ruby quirk, the local variables which can be assigned must be pre-declared. This is done with the local_names argument. For example:

# This works
obj = Object.new
Haml::Engine.new("%p= foo").def_method(obj, :render, :foo)
obj.render(:foo => "Hello!") #=> "<p>Hello!</p>"

# This doesn't
obj = Object.new
Haml::Engine.new("%p= foo").def_method(obj, :render)
obj.render(:foo => "Hello!") #=> NameError: undefined local variable or method `foo'

Note that Haml modifies the evaluation context (either the scope object or the self object of the scope binding). It extends Helpers, and various instance variables are set (all prefixed with haml_).

Parameters:

  • object (Object, Module)

    The object on which to define the method

  • name (String, Symbol)

    The name of the method to define

  • local_names (Array<Symbol>)

    The names of the locals that can be passed to the proc



219
220
221
222
223
224
# File 'lib/haml/engine.rb', line 219

def def_method(object, name, *local_names)
  method = object.is_a?(Module) ? :module_eval : :instance_eval

  object.send(method, "def #{name}(_haml_locals = {}); #{compiler.precompiled_with_ambles(local_names)}; end",
              @options[:filename], @options[:line])
end

- options_for_buffer



44
45
46
# File 'lib/haml/engine.rb', line 44

def options_for_buffer
  @options.for_buffer
end

- (String) render(scope = Object.new, locals = {}) Also known as: to_html

Processes the template and returns the result as a string.

scope is the context in which the template is evaluated. If it’s a Binding or Proc object, Haml uses it as the second argument to Kernel#eval; otherwise, Haml just uses its #instance_eval context.

Note that Haml modifies the evaluation context (either the scope object or the self object of the scope binding). It extends Helpers, and various instance variables are set (all prefixed with haml_). For example:

s = "foobar"
Haml::Engine.new("%p= upcase").render(s) #=> "<p>FOOBAR</p>"

# s now extends Haml::Helpers
s.respond_to?(:html_attrs) #=> true

locals is a hash of local variables to make available to the template. For example:

Haml::Engine.new("%p= foo").render(Object.new, :foo => "Hello, world!") #=> "<p>Hello, world!</p>"

If a block is passed to render, that block is run when yield is called within the template.

Due to some Ruby quirks, if scope is a Binding or Proc object and a block is given, the evaluation context may not be quite what the user expects. In particular, it’s equivalent to passing eval("self", scope) as scope. This won’t have an effect in most cases, but if you’re relying on local variables defined in the context of scope, they won’t work.

Parameters:

  • scope (Binding, Proc, Object) (defaults to: Object.new)

    The context in which the template is evaluated

  • locals ({Symbol => Object}) (defaults to: {})

    Local variables that will be made available to the template

  • block (#to_proc)

    A block that can be yielded to within the template

Returns:

  • (String)

    The rendered template



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/haml/engine.rb', line 110

def render(scope = Object.new, locals = {}, &block)
  parent = scope.instance_variable_defined?('@haml_buffer') ? scope.instance_variable_get('@haml_buffer') : nil
  buffer = Haml::Buffer.new(parent, @options.for_buffer)

  if scope.is_a?(Binding) || scope.is_a?(Proc)
    scope_object = eval("self", scope)
    scope = scope_object.instance_eval{binding} if block_given?
  else
    scope_object = scope
    scope = scope_object.instance_eval{binding}
  end

  set_locals(locals.merge(:_hamlout => buffer, :_erbout => buffer.buffer), scope, scope_object)

  scope_object.instance_eval do
    extend Haml::Helpers
    @haml_buffer = buffer
  end
  begin
    eval(@compiler.precompiled_with_return_value, scope, @options[:filename], @options[:line])
  rescue ::SyntaxError => e
    raise SyntaxError, e.message
  end
ensure
  # Get rid of the current buffer
  scope_object.instance_eval do
    @haml_buffer = buffer.upper if buffer
  end
end

- (Proc) render_proc(scope = Object.new, *local_names)

Returns a proc that, when called, renders the template and returns the result as a string.

scope works the same as it does for render.

The first argument of the returned proc is a hash of local variable names to values. However, due to an unfortunate Ruby quirk, the local variables which can be assigned must be pre-declared. This is done with the local_names argument. For example:

# This works
Haml::Engine.new("%p= foo").render_proc(Object.new, :foo).call :foo => "Hello!"
  #=> "<p>Hello!</p>"

# This doesn't
Haml::Engine.new("%p= foo").render_proc.call :foo => "Hello!"
  #=> NameError: undefined local variable or method `foo'

The proc doesn’t take a block; any yields in the template will fail.

Parameters:

  • scope (Binding, Proc, Object) (defaults to: Object.new)

    The context in which the template is evaluated

  • local_names (Array<Symbol>)

    The names of the locals that can be passed to the proc

Returns:

  • (Proc)

    The proc that will run the template



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/haml/engine.rb', line 165

def render_proc(scope = Object.new, *local_names)
  if scope.is_a?(Binding) || scope.is_a?(Proc)
    scope_object = eval("self", scope)
  else
    scope_object = scope
    scope = scope_object.instance_eval{binding}
  end

  begin
    eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" +
         compiler.precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line])
  rescue ::SyntaxError => e
    raise SyntaxError, e.message
  end
end