Last active
December 1, 2016 09:15
-
-
Save peter/e05ed4d45c34174d17d795329db488f9 to your computer and use it in GitHub Desktop.
Using handlebars.rb (handlebars.js) from Rails 4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################ | |
# config/initializers/handlebars.rb: | |
################################################################ | |
template_path = File.join(Rails.root.to_s, 'app/views') | |
helpers = { | |
t: lambda do |context, key| | |
I18n.t(key) | |
end, | |
path: lambda do |context, path_name| | |
Seashore::Gangway::LocalUrlHelper.localized_path_for(path_name) | |
end, | |
css_classes: lambda do |context| | |
# NOTE: arrays in context are V8:Array instances, see: https://github.com/cowboyd/therubyracer/wiki/Accessing-V8-Objects-From-Ruby | |
css_classes = context['css_classes'].try(:to_a) | |
hide_from_classes = context['hide_from'].try(:to_a).try(:map) { |user_type| "hide-from-#{user_type}" } | |
[css_classes, hide_from_classes].compact.flatten.join(" ") | |
end, | |
join: lambda do |context, vals, sep| | |
vals && vals.join(sep || " ") | |
end, | |
ifEq: lambda do |context, val1, val2, block| | |
if val1 == val2 | |
block.fn(context) | |
else | |
block.inverse(context) | |
end | |
end | |
} | |
options = { | |
cache: !Rails.env.development?, | |
template_path: template_path, | |
partials_path: File.join(template_path, 'partials'), | |
helpers: helpers | |
} | |
Rails.configuration.handlebars_context = HandlebarsContext.new(options) | |
################################################################ | |
# app/models/handlebars_context.rb: | |
################################################################ | |
require 'handlebars' | |
class HandlebarsContext | |
PREFIX = '_' | |
EXT = '.hbs' | |
attr_reader :handlebars, :cached_templates, :cached_partials, :options | |
def initialize(options = {}) | |
options.assert_valid_keys(:cache, :template_path, :partials_path, :helpers) | |
default_options = {template_path: '.', partials_path: './partials', helpers: {}} | |
@options = default_options.merge(options) | |
@cached_templates = {} | |
@cached_partials = {} | |
@handlebars = Handlebars::Context.new | |
@handlebars.partial_missing do |name| | |
lambda do |this, context, options| | |
path = partial_path(name) | |
if partial = lookup_partial(path) | |
render_compiled(partial, context) | |
else | |
puts "[ERROR] HandlebarsContext could not find partial #{name} at path #{path}" | |
end | |
end | |
end | |
@options[:helpers].each do |name, block| | |
@handlebars.register_helper(name, &block) | |
end | |
end | |
def render(path, data) | |
template = lookup_template(template_path(path)) | |
if template | |
render_compiled(template, data) | |
else | |
puts "[ERROR] HandlebarsContext#render could not find template at path #{path}" | |
end | |
end | |
def lookup_template(path) | |
return @cached_templates[path] if @cached_templates[path] && options[:cache] | |
if File.exists?(path) | |
template_str = IO.read(path) | |
@cached_templates[path] = handlebars.compile(template_str) | |
else | |
nil | |
end | |
end | |
def lookup_partial(path) | |
return @cached_partials[path] if @cached_partials[path] && options[:cache] | |
if File.exists?(path) | |
template_str = IO.read(path) | |
@cached_partials[path] = handlebars.compile(template_str) | |
else | |
nil | |
end | |
end | |
private | |
def render_compiled(template, data) | |
template ? template.call(data) : nil | |
rescue Exception => e | |
puts "[ERROR] HandlebarsContext#render exception: #{e.message} #{e.backtrace.join("\n")}" | |
"" | |
end | |
def template_path(path) | |
filename = PREFIX + File.basename(path) + EXT | |
File.join(options[:template_path], File.dirname(path), filename) | |
end | |
def partial_path(name) | |
filename = PREFIX + name + EXT | |
File.join(options[:partials_path], filename) | |
end | |
end | |
################################################################ | |
# application_helper.rb: | |
################################################################ | |
def render_hbs(path, data) | |
Rails.configuration.handlebars_context.render(path, data).try(:html_safe) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment