
Security News
Astral Launches pyx: A Python-Native Package Registry
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
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.
This project is currently in maintenance mode. Here's what this means:
FlavourSaver is Copyright (c) 2013 Resistor 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:
{{some.method.chain}}
){{object.['index'].method}}
):
Ruby's :[](index)
method is called for literals, making FlavourSaver
compatible with Hash
and hashlike objects.{{method arg1 "arg2"}}
){{method foo=bar bar="baz"}}
){{method arg1 arg2 foo=bar bar="baz"}}
)
provided that the hash is the last argument.{{! a comment}}
){{{an expression}}}
){{{{raw}}}} not parsed or validated {{{{/raw}}}}
){{sum 1 (sum 1 1)}}
returns 3
)FlavourSaver implements the following helpers by default:
Yields its argument into the context of the block contents:
{{#with person}}
{{name}}
{{/with}}
Takes a single collection argument and yields the block's contents once for each member of the collection:
{{#each people}}
{{name}}
{{/each}}
Takes a single argument and yields the contents of the block if that argument is truthy.
{{#if person}}
Hi {{person.name}}!
{{/if}}
It can also handle a special case {{else}}
expression:
{{#if person}}
Hi {{person.name}}!
{{else}}
Nobody to say hi to.
{{/if}}
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
:
{{#each names}}
{{this}}
{{/each}}
Writes log output. The destination can be changed by assigning a Logger
instance to
FlavourSaver.logger=
. On Rails FlavourSaver.logger
automatically points at
Rails.logger
.
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:
<h1>Hello {{whom}}!</h1>
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:
{{#three_times}}
hello
{{/three_times}}
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:
{{#list_people people}}
<b>{{name}}<b><br />
Age: {{age}}<br />
Sex: {{sex}}<br />
{{/list_people}}
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:
{{#isFemale person}}
{{person.name}} is female.
{{else}}
{{person.name}} is male.
{{/isFemale}}
You can use a subexpression as any value for a helper, and it will be executed before it is ran. You can also nest them, and use them in assignment of variables.
Below are some examples, utilizing a "sum" helper than adds together two numbers.
{{sum (sum 5 10) (sum 2 (sum 1 4))}}
#=> 22
{{#if (sum 1 2) > 2}}its more{{/if}}
#=> its more
{{#student_heights size=(sum boys girls)}}
Sometimes you don't want a section of content to be evaluted as handlebars, such as when you want to display it in a page that renders with handlebars. FlavourSaver offers a raw
helper, that will allow you to pass anything through wrapped in those elements, and it will not be evaluated.
{{{{raw}}}}
{{if} this tries to parse, it will break on syntax
{{{{/raw}}}}
=> {{if} this tries to parse, it will break on syntax
Its important to note that while this looks like a block helper, it is not in practice. This is why you must omit the use of a #
when writing it.
Handlebars allows you to register a partial either as a function or a string template with the engine before compiling, FlavourSaver retains this behaviour (with the notable exception of within Rails - see below).
To register a partial you call FlavourSaver.register_partial
with a name and a string:
FlavourSaver.register_partial(:my_partial, "{{this}} is a partial")
You can then use this partial within your templates:
{{#each people}}{{> my_partial this}}{{/each}}
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 instance 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:
{{#if current_user}}
Welcome back, {{current_user.first_name}}!
{{/if}}
You can use the registered Tilt interface directly to render template strings with a hash of template variables.
The Tilt template's render
method expects an object that can respond to messages using dot notation. In the following example, the template variable {{foo}}
will result in a call to .foo
on the data
object. For this reason the data
object can't be a simple hash. A model would work, but if you have a plain old Ruby hash, use it to create a new OpenStruct object, which will provide the dot notation needed.
template = Tilt['handlebars'].new { "{{foo}} {{bar}}" }
data = OpenStruct.new foo: "hello", bar: "world"
template.render data # => "hello world"
In Handlebars.js all partial templates must be pre-registered with the engine before they are able to be used. When running inside Rails FlavourSaver modifies this behaviour to use Rails' render partial helper:
{{> my_partial}}
Will be translated into:
render :partial => 'my_partial'
Handlebars allows you to send a context object into the partial, which sets the execution
context of the partial. In Rails this behaviour would be confusing and non-standard, so
instead any argument passed to the partial is evaluated and passed to the partial's
:object
argument:
{{> my_partial my_context}}
render :partial => 'my_partial', :object => my_context
git checkout -b my-new-feature
)git commit -am 'Added some feature'
)git push origin my-new-feature
)FAQs
Unknown package
We found that flavour_saver demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
Security News
The Latio podcast explores how static and runtime reachability help teams prioritize exploitable vulnerabilities and streamline AppSec workflows.
Security News
The latest Opengrep releases add Apex scanning, precision rule tuning, and performance gains for open source static code analysis.