Handlebars.js without the .js
FlavourSaver is a ruby-based implementation of the Handlebars.js templating language. FlavourSaver supports Handlebars template rendering natively on Rails and on other frameworks (such as Sinatra) via Tilt.
Please use it, break it, and send issues/PR's for improvement.
FlavourSaver is Copyright (c) 2012 Sociable Limited and licensed under the terms of the MIT Public License (see the LICENSE file included with this distribution for more details).
Add this line to your application's Gemfile:
gem 'flavour_saver'
And then execute:
$ bundle
Or install it yourself as:
$ gem install flavour_saver
FlavourSaver provides an interface to the amazing Tilt templating library, meaning that it should work with anything that has Tilt support (Sinatra, etc) and has a native Rails template handler.
FlavourSaver is in its infancy, your pull requests are greatly appreciated.
Currently supported:
- Expressions:
- with object-paths (
{{some.method.chain}}
) - containing object-literals (
{{object.['index'].method}}
): Ruby's:[](index)
method is called for literals, making FlavourSaver compatible withHash
and hashlike objects. - with list arguments (
{{method arg1 "arg2"}}
) - with hash arguments (
{{method foo=bar bar="baz"}}
) - with list and hash arguments (
{{method arg1 arg2 foo=bar bar="baz"}}
) provided that the hash is the last argument. - Comments (
{{! a comment}}
) - Expression output is HTML escaped
- with object-paths (
- Safe expressions
- Expressions wrapped in triple-stashes are not HTML escaped (
{{{an expression}}}
)
- Expressions wrapped in triple-stashes are not HTML escaped (
- Block expressions
- Simple API for adding block helpers.
Coming soon:
- Partials
FlavourSaver implements the following helpers by default:
Yields it's argument into the context of the block contents:
Takes a single collection argument and yeilds the block's contents once for each member of the collection:
Takes a single argument and yields the contents of the block if that argument is truthy.
It can also handle a special case {{else}}
expression:
Exactly the same is #if
but backwards.
In JavaScript this
is a native keyword, in Ruby not-so-much. FlavourSaver's this
helper
returns self
:
Additional helpers can easy be added by calling FS.register_helper
, eg:
FS.register_helper(:whom) { 'world' }
Now if you were to render the following template:
You would receive the following output:
<h1>Hello world!</h1>
Creating a block helper works exactly like adding a regular helper, except that
the helper implementation can call yield.contents
one or more times, with an
optional argument setting the context of the block execution:
FS.register_helper(:three_times) do
yield.contents
yield.contents
yield.contents
end
Which when called with the following template:
would result in the following output:
hello
hello
hello
Implementing a simple iterator is dead easy:
FS.register_helper(:list_people) do |people|
people.each do |person|
yield.contents person
end
end
Which could be used like so:
Block helpers can also contain an {{else}}
statement, which, when used creates
a second set of block contents (called inverse
) which can be yielded to the output:
FS.register_helper(:isFemale) do |person,&block|
if person.sex == 'female'
block.call.contents
else
block.call.inverse
end
end
You can also register an existing method:
def isFemale(person)
if person.sex == 'female'
yield.contents
else
yield.inverse
end
end
FS.register_helper(method(:isFemale))
Which could be used like so:
One potential gotcha of using FlavourSaver with Rails is that FlavourSaver doesn't let you have any access to the controller's instance variables. This is done to maintain compatibility with the original JavaScript implementation of Handlebars so that templates can be used on both the server and client side without any change.
When accessing controller isntance variables you should access them by way of a helper method or a presenter object.
For example, in ApplicationController.rb
you may have a before_filter
which authenticates
the current user's session cookie and stores it in the controller's @current_user
instance
variable.
To access this variable you could create a simple helper method in ApplicationHelpers
:
def current_user
@current_user
end
Which would mean that you are able to access it in your template:
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request