Class List Method List File List

# Class: Haml::Engine

Inherits:
  Object
  - Object
  - Haml::Engine
  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)

- - compiler

  Returns the value of attribute compiler.

- - (String) indentation

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

- - options

  The Haml::Options instance.

- - parser

  Returns the value of attribute parser.

## Instance Method Summary (collapse)

- - 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.

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

  Precompiles the Haml template.

- - options_for_buffer
- - (String) render(scope = Object.new, locals = {}, &block) (also: #to_html)

  Processes the template and returns the result as a string.

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

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

### 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:

- template (`String`) —

  The Haml template

- options (`{Symbol => Object}`) (defaults to: `{}`) —

  An options hash; see the Haml options documentation

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 = {}, &block) 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