#295 Sharing Mustache Templates pro
Mustache is a simple, logic-less templating language which allows you to use the same template for both Ruby and JavaScript. See how to set it up with a custom template handler in this episode.
- Download:
- source codeProject Files in Zip (93.7 KB)
- mp4Full Size H.264 Video (48.4 MB)
- m4vSmaller H.264 Video (21.2 MB)
- webmFull Size VP8 Video (23.3 MB)
- ogvFull Size Theora Video (55.6 MB)
Resources
bash
mkdir -p vendor/assets/javascripts curl https://raw.github.com/janl/mustache.js/master/mustache.js > vendor/assets/javascripts/mustache.js
products/index.html.erb
<div id="products" data-json-url="<%= products_url(:format => :json) %>"> <% @products.each do |product| %> <%= render "product", :mustache => product_for_mustache(product) %> <% end %> </div> <script type="text/html" id="product_template"> <%= render "product" %> </script>
products/_product.html.mustache
<div class="product"> <h2><a href="{{url}}">{{name}}</a></h2> <div class="details"> {{price}} {{#released_at}} | Released {{released_at}} {{/released_at}} </div> </div>
config/initializers/mustache_template_handler.rb
module MustacheTemplateHandler def self.call(template) if template.locals.include? :mustache "Mustache.render(#{template.source.inspect}, mustache).html_safe" else "#{template.source.inspect}.html_safe" end end end ActionView::Template.register_template_handler(:mustache, MustacheTemplateHandler)
products_helper.rb
def product_for_mustache(product) { url: product_url(product), name: product.name, price: number_to_currency(product.price), released_at: product.released_at.try(:strftime, "%B %e, %Y") } end
products_controller.rb
def index @products = Product.order("name").limit(10) @products = @products.offset((params[:page].to_i-1)*10) if params[:page].present? respond_to do |format| format.html format.json do render json: @products.map { |p| view_context.product_for_mustache(p) } end end end
products.js.coffee
jQuery -> if $('#products').length new ProductsPager() class ProductsPager constructor: (@page = 1) -> $(window).scroll(@check) check: => if @nearBottom() @page++ $(window).unbind('scroll', @check) $.getJSON($('#products').data('json-url'), page: @page, @render) nearBottom: => $(window).scrollTop() > $(document).height() - $(window).height() - 50 render: (products) => for product in products $('#products').append Mustache.to_html($('#product_template').html(), product) $(window).scroll(@check) if products.length > 0