Skip to content

Instantly share code, notes, and snippets.

@gabe
Created June 28, 2009 19:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save gabe/137356 to your computer and use it in GitHub Desktop.
Save gabe/137356 to your computer and use it in GitHub Desktop.
Routing & URI generation using URI Templates in Sinatra
require 'addressable/template'
module Juxt
module Sinatra
# Allows for declared, named URI Templates in Sinatra applications,
# for both routing and URI generation.
#
# The URI generation method (included as a Sinatra helper) modifies
# the path of generated URIs with request.script_name, meaning the
# URIs generated will still be valid if multiple Sinatra applications
# are hosted in the same application, using Rack::Builder.
#
# Requires Addressable (http://github.com/sporkmonger/addressable/tree/master).
#
# == Example
#
# class MyApplication < Sinatra::Base
# extend Juxt::Sinatra::URITemplates
#
# uri :index, '/'
# uri :entry, '/entries/{id}'
#
# get :index do
# "Hello"
# end
#
# get :entry do
# "The URI of this entry is #{uri(:entry, 'id' => params[:id])}"
# end
# end
module URITemplates
def reset_uri_templates!
@uri_templates = {}
end
# Declare a named URI Template for use in this application, and
# in subclasses of this application.
def uri(name, template)
@uri_templates[name] = Addressable::Template.new(template)
end
# Gets the merged URI Template collection for this application,
# and all superclasses.
def uri_templates
if superclass.respond_to?(:uri_templates)
superclass.uri_templates.merge(@uri_templates)
else
@uri_templates
end
end
private
# Override Sinatra route compilation (dirty).
def compile(path)
super(uri_templates[path] || path)
end
def inherited(subclass)
subclass.reset_uri_templates!
super
end
# Initialize the URI Template collection for the application
# being extended, and add a Sinatra helper for expanding
# templates, by name.
def self.extended(extendee)
extendee.reset_uri_templates!
extendee.helpers(Helpers)
end
module Helpers
def uri(name, *args)
template = self.class.uri_templates[name]
if template.nil?
return nil
end
args[0] ||= {}
uri = template.expand(*args)
uri.path = request.script_name + uri.path
uri
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment