## Handlebars.rb [![Gem Version](https://badge.fury.io/rb/handlebars.png)](http://badge.fury.io/rb/handlebars) [![Build Status](https://travis-ci.org/cowboyd/handlebars.rb.png?branch=master)](https://travis-ci.org/cowboyd/handlebars.rb) [![Dependency Status](https://gemnasium.com/cowboyd/handlebars.rb.png)](https://gemnasium.com/cowboyd/handlebars.rb) This uses [therubyracer][1] to bind to the _actual_ JavaScript implementation of [Handlebars.js][2] so that you can use it from ruby. ## Usage ### Simple stuff require 'handlebars' handlebars = Handlebars::Context.new template = handlebars.compile("{{say}} {{what}}") template.call(:say => "Hey", :what => "Yuh!") #=> "Hey Yuh!" ### functions as properties template.call(:say => "Hey ", :what => lambda {|this| ("yo" * 2) + "!"}) #=> "Hey yoyo!" ### Block Helpers: Just like JavaScript, you can write block helpers with an `{{else}}` section. To print out a section twice if a condition is met: # V8 maps the first argument sent to a block to "this". All subsequent arguments are as # described in the Handlebars documentation. handlebars.register_helper(:twice) do |context, condition, block| if condition "#{block.fn(context)}#{block.fn(context)}" else block.inverse(context) end end template = handlebars.compile("{{#twice foo}}Hurray!{{else}}Boo!{{/twice}}") template.call(foo: true) #=> Hurray!Hurray! template.call(foo: false) #=> Boo! ### Private variables: Just like JavaScript, block helpers can inject private variables into their child templates. These can be accessed in a template using the `@` prefix: handlebars.register_helper(:list) do |this, context, block| "" end template = handlebars.compile("{{#list array}}{{@index}}. {{title}}{{/list}}") template.call(array: [{title: "Memento"}, {title: "Inception"}]) #=> "" ### Hash arguments: When using hash arguments, beware of one gotcha - V8 defines the #hash method for every object. Therefore, to access the hash object of the options argument Handlebars sends to your block, you must use the `[]` method: handlebars.register_helper :list do |this, context, options| attrs = options[:hash].map{|k,v| "#{k}=\"#{v}\""}.join(' ') "" end template = handlebars.compile(%({{#list nav id="nav-bar" class="top"}}{{title}}{{/list}})) template.call({nav: [{url: 'www.google.com', title: 'Google'}]}) #=> ### Safe Strings By default, handlebars will escape strings that are returned by your block helpers. To mark a string as safe: template = handlebars.compile("{{safe}}") template.call(:safe => proc {Handlebars::SafeString.new("
Totally Safe!
")})

### Partials

You can directly register partials

    handlebars.register_partial("whoami", "I am {{who}}")
    handlebars.compile("{{>whoami}}").call(:who => 'Legend') #=> I am Legend

Partials can also be dynamically looked up by defining a partial_missing behavior:

    handlebars.partial_missing do |name|
      "unable to find >#{name}"
    end
    handlebars.compile("{{>missing}}").call #=> unable to find >missing

Missing partials can also be returned as a function:

    count = 0
    handlebars.partial_missing do |name|
      lambda do |this, context, options|
        count += 1
        "#{count} miss(es) when trying to look up a partial"
      end
    end
    t = handlebars.compile("{{>missing}}")
    t.call #=> 1 miss(es) when trying to look up a partial
    t.call #=> 2 miss(es) when tyring to look up a partial

### Security

In general, you should not trust user-provided templates: a template can call any method
(with no arguments) or access any property on any object in the `Handlebars::Context`.

If you'd like to render user-provided templates, you'd want to make sure you do so in a
sanitized Context, e.g. no filesystem access, read-only or no database access, etc.

## Test

    rspec spec/


[1]: http://github.com/cowboyd/therubyracer "The Ruby Racer"
[2]: http://github.com/wycats/handlebars.js "Handlebars JavaScript templating library"