Práctica: Añadir Template Haml a Rock, Paper, Scissors

Use Haml para crear un template index.haml en un directorio views.

[~/local/src/ruby/sinatra/rack/rack-rock-paper-scissors(template)]$ tree
.
|--- README
|--- Rakefile
|--- rps.rb
`--- views
    `--- index.haml
El template puede ser usado así:
require 'rack/request'
require 'rack/response'
require 'haml'

module RockPaperScissors
  class App 
     ...

    def call(env)
      ...
      engine = Haml::Engine.new File.open("views/index.haml").read
      res = Rack::Response.new 
      res.write engine.render({}, 
        :answer => answer, 
        :choose => @choose,
        :throws => @throws)
      res.finish
    end # call
  end   # App
end     # RockPaperScissors

Véase:

  1. Haml::Engine

La sintáxis del método render es:

  (String) render(scope = Object.new, locals = {})
También se puede usar como to_html. Procesa el template y retorna el resultado como una cadena.

El parámetro scope es el contexto en el cual se evalúa el template.

Si es un objeto Binding haml lo usa como segundo argumento de Kernel#eval (Véase la sección Bindings (encarpetados) y eval en 15.2.1) en otro caso, haml utiliza #instance_eval.

Nótese que Haml modifica el contexto de la evaluación (bien el objeto ámbito o el objeto self del ámbito del binding). Se extiende Haml::Helpers y se establecen diversas variables de instancia (todas ellas prefijadas con haml_).

Por ejemplo:

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

Ahora s extiende Haml::Helpers :

s.respond_to?(:html_attrs) #=> true

Haml::Helpers contiene un conjunto de métodos/utilidades para facilitar distintas tareas. La idea de que estén disponibles en el contexto es para ayudarnos dentro del template. Por ejemplo el método

- (String) escape_once(text)
Escapa las entidades HTML en el texto.

locals es un hash de variables locales que se deja disponible dentro del template. Por ejemplo:

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

Si se pasa un bloque a render el bloque será ejecutado en aquellos puntos en los que se llama a yield desde el template.

Debido a algunas peculiaridades de Ruby, si el ámbito es un Binding y se proporciona también un bloque, el contexto de la evaluación puede no ser el que el usuario espera.

Parametros:

  1. scope (Binding, Proc, Object) (por defecto: Object.new). El contexto en el que se evalúa el template

  2. locals ({Symbol => Object}) (por defecto: {}). Variables locales que se dejan disponibles en el template
  3. block (#to_proc) Un bloque que será llamado desde el template.

  4. Retorna una String con el template renderizado

Casiano Rodriguez León 2015-01-07