Created
December 3, 2009 15:58
-
-
Save vasil/248260 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
module Sinatra | |
#class TemplateNotFound < Sinatra::NotFound | |
class TemplateNotFound < Sinatra::ShowExceptions | |
end | |
module Partials | |
# Render a partial template. [Adapted from Merb] | |
# | |
# ==== Parameters | |
# template<~to_s>:: | |
# The path to the template, relative to the views dir; | |
# absolute path will work too. | |
# opts<Hash>:: A hash of options (see below) | |
# | |
# ==== Options (opts) | |
# :with<Object, Array>:: | |
# An object or an array of objects that will be passed into the partial. | |
# :as<~to_sym>:: The local name of the :with Object inside of the partial. | |
# others:: | |
# A Hash object names and values that will be the local names and values | |
# inside the partial. | |
# | |
# ==== Examples | |
# partial :foo, :hello => @object | |
# | |
# The "_foo" partial will be called, relative to the views dir, | |
# with a local variable of +hello+ inside of it, assigned to @object. | |
# | |
# partial :bar, :with => ['one', 'two', 'three'] | |
# | |
# The "_bar" partial will be called once for each element of the array | |
# specified by :with for a total of three iterations. Each element | |
# of the array will be available in the partial via a local variable named | |
# +bar+. Additionally, there will be two extra local variables: | |
# +collection_index+ and +collection_size+. +collection_index+ is the index | |
# of the object currently referenced by +bar+ in the collection passed to | |
# the partial. +collection_size+ is the total size of the collection. | |
# | |
# By default, the object specified by :with will be available through a | |
# local variable with the same name as the partial template. However, | |
# this can be changed using the :as option. | |
# | |
# partial :bar, :with => "one", :as => :number | |
# | |
# In this case, "one" will be available in the partial through the local | |
# variable named +number+. | |
def partial(template, opts={}) | |
# partial :foo becomes "./_foo" | |
# partial "foo/bar" becomes "foo/_bar" | |
template = template.to_s | |
if template =~ %r{^/} | |
template_path = File.dirname(template) / "_#{File.basename(template)}" | |
else | |
template_path = (m = template.match(/.*(?=\/)/)) ? m[0] : '.' | |
end | |
template = "_#{File.basename(template)}" | |
# This handles no :with as well | |
with = [opts.delete(:with)].flatten | |
as = (opts.delete(:as) || template.match(%r[(?:.*/)?_([^\./]*)])[1]).to_sym | |
# Ensure that as is in the locals hash even if it isn't passed in here | |
# so that it's included in the preamble. | |
locals = opts.merge(:collection_index => -1, :collection_size => with.size, as => opts[as]) | |
template_full = File.join(template_path, template) | |
# this handles an edge-case where the name of the partial is _foo.* and your opts | |
# have :foo as a key. | |
named_local = opts.key?(as) | |
with.inject('') do |rendered, temp| | |
locals[as] = temp unless named_local | |
if File::exists?(File.join(Sinatra::Application.views, template_full)) | |
locals[:collection_index] += 1 | |
rendered << erb(:"#{template_full}", {}, locals) | |
else | |
raise TemplateNotFound, "Could not find template at #{template_path}.*" | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment