Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add rails support
* Templates go in app/templates/{controller}/{action}.{mime}.mustache

* Mustaches (ie, the ruby classes) go under
  app/views/{controller}/{action}.rb and should inherit from
  Mustache::Rails

* Controller ivars will be copied to your mustache class.

* You can omit declaring the Mustache. In that case, an instance of
  Mustache::Rails will be used for evaluation. If this is the case, then
  attr_readers will be defined for your controller ivars, since you can't
  access them directly from the template.

* Mustache::Rails also delegates any methods to the ActionView::Base
  instance used by rails, so helpers should work fine.

* You can't use Mustache's {{< partial }} syntax. Yet.

* There's no way to use the form helpers from rails in a mustache
  template, but alternate solutions like Bureaeucrat
  (http://github.com/tizoc/bureaucrat) which ports django's form objects
  into ruby might be useful.

* Templates can go in app/views/{controller}/{action}.{mime}.mustache
  still, if you prefer to keep them alongside your views. Mustache will
  just look for them in app/templates before.
  • Loading branch information
foca committed Oct 10, 2009
1 parent ca40124 commit 99cd770
Showing 1 changed file with 58 additions and 0 deletions.
58 changes: 58 additions & 0 deletions lib/mustache/rails.rb
@@ -0,0 +1,58 @@
require "mustache"

class Mustache::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
end

class Mustache::Rails::TemplateHandler < ActionView::TemplateHandler
def render(template, local_assigns, &block)
mustache = _mustache_class_from_template(template)
mustache.template_file = template.filename

returning mustache.new do |result|
_copy_instance_variables_to(result)
result.view = @view
result[:yield] = @view.instance_variable_get(:@content_for_layout)
result.context.update(local_assigns)
end.to_html
end

def _copy_instance_variables_to(mustache)
variables = @view.controller.instance_variable_names
variables -= %w(@template)

if @view.controller.respond_to?(:protected_instance_variables)
variables -= @view.controller.protected_instance_variables
end

variables.each do |name|
mustache.instance_variable_set(name, @view.controller.instance_variable_get(name))
end

# If you're using an anonymous mustache, then you probably want
# +attr_reader+ declared for your instance variables, else there's no way
# you can access them on the template.
if mustache.class == Mustache
mustache.class.class_eval do
attr_reader *variables.map {|name| name.to_s.gsub(/^@/, '') }
end
end
end

def _mustache_class_from_template(template)
const_name = [template.base_path, template.name].compact.join("/").classify
defined?(const_name) ? const_name.constantize : Mustache::Rails
end
end

ActiveSupport::Dependencies.load_paths << Rails.root.join("app", "views").to_s
ActionController::Base.prepend_view_path(Rails.root.join("app", "templates").to_s)
ActionView::Template.register_template_handler(:mustache, Mustache::Rails::TemplateHandler)

0 comments on commit 99cd770

Please sign in to comment.