• Stars
    star
    166
  • Rank 227,748 (Top 5 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 13 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

mustache and handlebars template handling in Rails 3.x and Rails 4.x

stache

A Rails 3.x, Rails 4.x, and Rails 5.x compatible Mustache/Handlebars template handler, with support for partials and a couple extra niceties to make sharing the raw templates with client-side javascript a little easier. It's a one-stop shop for your facial-hair-inspired templates.

Build Status

Mustache template caching is in 1.1+

I'm investigating whether or not this is something that can be/needs to be ported to handlebars.

Rails 4, Rails 5 Support is in 1.0.3+

If you want Rails 4 or Rails 5 support, you'll have to use 1.0.3.

Installation

gem "mustache" # or "handlebars"
gem "stache"

Install the gem. If you want to override any of the configuration options (see stache/config), toss an initializer in config/initializers and:

Stache.configure do |c|
  # This is probably the one you'll want to change
  # it defaults to app/templates
  c.template_base_path = "..."

  # This lets you indicate the name of a module that
  # namespaces all your view classes, useful, if you
  # have a naming conflict, such as with a mailer
  c.wrapper_module_name = "..."

  # N.B. YOU MUST TELL STACHE WHICH TO USE:
  c.use :mustache
  # and / or
  c.use :handlebars

  # Set it to true if template path should be included in
  # script's id tag as a underscored prefix. It can be
  # overwritten by an id param in `#template_include_tag`.
  c.include_path_in_id = false

  # Caching (new in 1.1.0, Mustache-only for now)
  # Any ActiveSupport::Cache should work fine.
  # If you enable this in development, you will lose automagical template reloading!
  c.template_cache = ActiveSupport::Cache::MemoryStore.new if Rails.env.production?
end

# or if the block style ain't yer thang, just:
Stache.template_base_path = File.join(Rails.root, "app", "şablon")
Stache.template_cache = ActiveSupport::Cache::MemoryStore.new if Rails.env.production?

Helper methods

There is currently just one helper method; template_include_tag. If you pass it the name of a partial it will write out the contents of the partial in a script tag, so that you can access it from within your JavaScript.

<%= template_include_tag 'profiles/profile' %>

Specify the template to include with a path relative to your template base path (i.e. profiles/profile rather than just profile).

A View Class of your Very Own

To facilitate easy integration, 'Stache comes packaged with a fully-functioning subclass of Mustache, called Stache::Mustache::View. It will try to find a more appropriate view class to provide to the template renderer based on the template name, but if one cannot be found it will automatically give ya a Stache::Mustache::View so you can have something.

Needless to say, it's probably better if your custom View objects are subclasses of Stache::Mustache::View. That way we can all be sure that the handler will render correctly.

An example by way of explanation:

With a template app/templates/profiles/index, Stache will look for a view named Profiles::Index, and, if not found, will just use the base Stache::Mustache::View. Stache adds app/views to Rails' autoload paths, so here's a sample directory structure and some sample files:

app/
  templates/
    profiles/
      index.html.mustache
  views/
    profiles/
      index.rb
# in profiles/index.rb
module Profiles
  class Index < ::Stache::Mustache::View
    def my_view_helper_method
      "whoo"
    end
  end
end
<!-- in the view, then -->
<p>Here's a helper_method call: {{ my_view_helper_method }}</p>

With the wrapper_module_name configuration set to "Wrapper":

With a template app/templates/profiles/index, Stache will look for a view named Wrapper::Profiles::Index, and, if not found, will just use the base Stache::Mustache::View.

Handlebars?

Handlebars will have full access to your rails view helpers.

I'm a handlebars template. Look at me call a helper: {{{image_path my_image}}}

You can subclass Stache::Handlebars::View in the same way as mustache above, but there isn't as much point in doing so.

View Specs

Yes, you can write view specs using RSpec for your Stache templates! You can use RSpec's assign method to assign values to view instance variables, which will then be be available to the Stache view, either as instance variables, or via an accessor. Any instance variables defined in the RSpec example will also be similarly available, so

    it "should display my instance variable" do
      assign(:resource, "Foo")
      render
      ...
    end

and

    it "should display my instance variable" do
      @resource = "Foo"
      render
      ...
    end

both make @resource available to the Stache view.

Non-Mustache Partials

Yes, you can include non-Mustache partials (and templates) in your Stache templates. However, the {{>partial_name_here}} syntax in the template won't find a non-Mustache template. You can define a method in the view and reference it in the template. The view method should use @view.render to render the non-Mustache partial and return its content. Example:

Mustache template:

    {{{my_haml_sidebar}}}

View:

   class MyPage < ::Stache::Mustache::View
     def my_haml_sidebar
       @view.render partial: 'somewhere/some_haml_partial_name'
     end
   end

Stache + ActionMailer

Stache should work just fine with ActionMailer, with one minor configuration:

Assuming you have a view directory like this:

views/
  user_mailer/
    confirm_sign_up.html.mustache
    confirm_sign_up.rb
    confirm_sign_up.text.mustache

You'd define your UserMailer like so:

class UserMailer < ActionMailer::Base
  default from: '[email protected]'

  def confirm_sign_up
    mail(to: '[email protected]', subject: 'Welcome to StacheMail') do |format|
      format.text
      format.html
    end
  end
end

N.B. the do |format| block is very important: ActionMailer will render the code in the .rb file as a multipart text/html component, which is probably not what you want unless you really want to show off your View class to all your recipients :).

The confirm_sign_up.rb file contains an utterly normal ::Stache::Mustache::View subclass, e.g. Note that it is nested inside the UserMailer class.

class UserMailer
  class ConfirmSignUp < ::Stache::Mustache::View
    def full_name
      ["Bob", "Jones"].join(' ')
    end
  end
end

Of Note

This is code that was ripped out of a research project. It probably has some rough edges.

Thanks to

This project builds on work done by the following people and projects:

So: thanks a ton to those guys.

Contributors

  • afeld provided 1.8.7 compatibility fixes.
  • subwindow provided some much needed love for Stache::Mustache::View exception handling.
  • solotimes provided better support for non-standard encodings.
  • ajacksified cleaned up template extension handling.
  • ayamomiji extended the #template_include_tag to pass through the full range of #content_tag options.
  • awestendorf requested that View#partial not be so particular about leading underscores. Though I didn't use his code, his prompt lead me to investigate how to properly use Rails' internal template lookup code.
  • zombor contributed an overhaul to the Mustache renderer that puts Mustache classes themselves in control of the render chain, not Rails.
  • kategengler contributed a patch to allow folks to specify a namespace for their view objects.
  • joker1007 contributed a patch making the autoload paths setup more broadly compatible.
  • kianw contributed a patch making RSpec a little easier to use.
  • MarkusHarmsen added Mustache caching, leading to HUGE performance increases. Thanks!
  • kimili added Rails 5.x compatibility as well as some generators and configuration options.

Thanks a ton to all of the contributors, equally. This would never have grown beyond a mediocre tool that rendered partials without their help!

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright (c) 2011-2017 Matt Wilson / Agora Games. See LICENSE for details.

More Repositories

1

leaderboard

Leaderboards backed by Redis in Ruby
Ruby
478
star
2

kairos

Python module for time series data in Redis and Mongo
Python
207
star
3

haigha

AMQP Python client
Python
161
star
4

leaderboard-python

Leaderboards backed by Redis in Python
Python
156
star
5

nginx-google-oauth

Lua module to add Google OAuth to nginx
Lua
141
star
6

activity_feed

Activity feeds backed by Redis
Ruby
135
star
7

amico

Relationships (e.g. friendships) backed by Redis
Ruby
112
star
8

confirm-with-reveal

Replacement for window.confirm() using the Reveal modal popup plugin from ZURB Foundation.
CoffeeScript
50
star
9

bracket_tree

Tree-based Bracketing System
Ruby
49
star
10

tassadar

A Starcraft 2 replay parser written in pure Ruby
Ruby
44
star
11

torus

A service implementing the Carbon protocol and storing time series data using kairos
Python
42
star
12

chai

Mocking framework for Python
Python
40
star
13

oembedr

Lightweight, Flexible OEmbed Consumer Library
Ruby
37
star
14

php-leaderboard

Leaderboards backed by Redis in PHP
PHP
25
star
15

leaderboard-coffeescript

Leaderboards backed by Redis in CoffeeScript
CoffeeScript
24
star
16

java-leaderboard

Leaderboards backed by Redis in Java
Java
24
star
17

factory-worker

Factories for NodeJS
JavaScript
23
star
18

bnet_scraper

A Nokogiri-based scraper of Battle.net profiles. Currently this only includes Starcraft2.
Ruby
22
star
19

python-leaderboard

Leaderboards backed by Redis in Python
Python
21
star
20

halo-reach-api

Ruby gem for interacting with the Halo:Reach API
Ruby
15
star
21

soonatra

Sinatra application to show a “Coming Soon” page and collect emails.
Ruby
14
star
22

GWFSelect-for-jQuery-UI

Google WebFont selection drop-down widget for jQuery UI.
JavaScript
13
star
23

amico-python

Relationships (e.g. friendships) backed by Redis
Python
11
star
24

php-bracket_tree

Tree-based Bracketing System
PHP
10
star
25

strumbar

Strumbar is a wrapper around ActiveSupport::Notifications with preconfigurations for basic instrumentation to be sent to statsd.
Ruby
9
star
26

scala-leaderboard

Leaderboards backed by Redis in Scala
Scala
7
star
27

vindicia-api

A wrapper for creating queries to the Vindicia CashBox API
Ruby
7
star
28

windbag

Notification System for Rails 3.1+
Ruby
6
star
29

pyevent

Python extension module for Niels Provos' libevent
Python
6
star
30

node-amico

NodeJS port of amico (Relationships (e.g. friendships) backed by Redis) using CoffeeScript.
CoffeeScript
6
star
31

ventilation

Ruby
6
star
32

improved_logging

Adds improved logging capabilities to the ActiveSupport::BufferedLogger class
Ruby
5
star
33

bracketeer

BracketTree Visual Template Creator
Ruby
4
star
34

seed_list

Seed management for tournament brackets
Ruby
3
star
35

tassadar-server

A web service interface to the tassadar Starcraft 2 replay parser
Ruby
3
star
36

leaderboard_factory

Nice little package to help you with leaderboards when you need a lot of them.
Ruby
3
star
37

py-eventsocket

Python
3
star
38

notify-campfire-multi

Notify multiple campfire rooms from a post-commit svn hook
Ruby
2
star
39

silver_spoon

Entitlements in Redis
Ruby
2
star
40

mm_sortable_item

A tiny MongoMapper plugin to provide some basic list functionality.
Ruby
2
star
41

javascripto

Client-side Javascript Application Framework
Ruby
2
star
42

saltstack-sandbox

A Vagrant-based sandbox environment for experimenting with SaltStack
2
star
43

hydra-async-demo

This is a user facing tutorial that will help guide users through the usage of Hydra Studio to support an asynchronous multiplayer game.
C#
2
star
44

read-and-write-if-nil

Pass through the value of a block to a cache key if the value is nil when it's requested
Ruby
1
star
45

ruby-openid-oauth-hybrid

ruby-openid-2.1.2 with added support for the openid-oauth hybrid extention
Ruby
1
star
46

bcms_xml_data_feed

JavaScript
1
star
47

website-middleman

Company public site and blog, rendered to static files by Middleman.
SCSS
1
star
48

gondola

Ruby
1
star
49

seedlings

Simple seed data management
Ruby
1
star
50

bcms_twitter

Twitter integration for BrowserCMS
JavaScript
1
star
51

beta

Beta access restriction library
Ruby
1
star
52

test-runner-benchmark

Benchmarking your tests
Ruby
1
star
53

action-mailer-with-temporary-delivery-method

Send email using ActionMailer but without using the templates or changing your smtp_settings
Ruby
1
star