Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
goodmike committed Jun 25, 2010
0 parents commit ef859dc
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 0 deletions.
6 changes: 6 additions & 0 deletions config/initializers/mustache.rb
@@ -0,0 +1,6 @@
# Be sure to install mustache gem and include mustache gem in project Gemfile.

# Template Handler
require 'mustache_rails'
# Generator
Rails.application.config.generators.template_engine :mustache_generator
134 changes: 134 additions & 0 deletions lib/mustache-rails.rb
@@ -0,0 +1,134 @@
require 'action_view'
require 'active_support'
require 'mustache'

class Mustache

# TODO - Think about allowing to overwrite layout methods in subclassing views
# http://github.com/defunkt/mustache/blob/master/lib/mustache/sinatra.rb#L79-82
# http://github.com/defunkt/mustache/blob/master/lib/mustache/sinatra.rb#L96-102

# Remember to use {{{yield}}} (3 mustaches) as this shouldn't be escaped.
# Using {{{tag}}} will skip escaping HTML so if your mustache methods return
# HTML, be sure to interpolate them using 3 mustaches.

# Subclass Mustache::Rails for your view files. Place view files in
# app/views/:controller/:action.rb.

# Mustache::Rails registers a TemplateHandler for ".rb" files. Templates go in
# app/templates/:controller/:action.format.mustache

class Rails < Mustache
attr_accessor :view

def method_missing(method, *args, &block)
view.send(method, *args, &block)
end

def respond_to?(method, include_private=false)
super(method, include_private) || view.respond_to?(method, include_private)
end

# Redefine where Mustache::Rails templates locate their partials:
#
# (1) in the same directory as the current template file.
# (2) in the shared templates path (can be configured via Config.shared_path=(value))
#
def partial(name)
partial_name = "#{name}.#{Config.template_extension}"
template_dir = Pathname.new(self.class.template_file).dirname
partial_path = File.expand_path("#{template_dir}/#{partial_name}")
unless File.file?(partial_path)
partial_path = "#{Config.shared_path}/#{partial_name}"
end
File.read(partial_path)
end

# You can change these defaults in, say, a Rails initializer or
# environment.rb, e.g.:
#
# Mustache::Rails::Config.template_base_path = Rails.root.join('app', 'templates')
module Config
def self.template_base_path
@template_base_path ||= ::Rails.root.join('app', 'templates')
end

def self.template_base_path=(value)
@template_base_path = value
end

def self.template_extension
@template_extension ||= 'html.mustache'
end

def self.template_extension=(value)
@template_extension = value
end

def self.shared_path
@shared_path ||= ::Rails.root.join('app', 'templates', 'shared')
end

def self.shared_path=(value)
@shared_path = value
end
end

class TemplateHandler < ActionView::Template::Handler

include ActionView::Template::Handlers::Compilable

self.default_format = :mustache

# @return [String] its evaled in the context of the action view
# hence the hack below
#
# @param [ActionView::Template]
def compile(template)
mustache_class = mustache_class_from_template(template)
mustache_class.template_file = mustache_template_file(template)

<<-MUSTACHE
mustache = ::#{mustache_class}.new
mustache.view = self
mustache[:yield] = content_for(:layout)
mustache.context.update(local_assigns)
variables = controller.instance_variable_names
variables -= %w[@template]
if controller.respond_to?(:protected_instance_variables)
variables -= controller.protected_instance_variables
end
variables.each do |name|
mustache.instance_variable_set(name, controller.instance_variable_get(name))
end
# Declaring an +attr_reader+ for each instance variable in the
# Mustache::Rails subclass makes them available to your templates.
mustache.class.class_eval do
attr_reader *variables.map { |name| name.sub(/^@/, '').to_sym }
end
mustache.render
MUSTACHE
end

private

def mustache_class_from_template(template)
const_name = ActiveSupport::Inflector.camelize(template.virtual_path.to_s)
defined?(const_name) ? const_name.constantize : Mustache
end

def mustache_template_file(template)
virtual_path = template.virtual_path.sub('alfred/views/','')
"#{Config.template_base_path}/#{virtual_path}.#{Config.template_extension}"
end

end
end
end

::ActiveSupport::Dependencies.load_paths << Rails.root.join("app", "views")
::ActionView::Template.register_template_handler(:rb, Mustache::Rails::TemplateHandler)

0 comments on commit ef859dc

Please sign in to comment.