Permalink
Browse files

add multi route extension

  • Loading branch information...
1 parent 563b242 commit 12b184d170428ca3ac1abd2100df57b5aad46cae @rkh rkh committed Sep 5, 2011
Showing with 134 additions and 1 deletion.
  1. +3 −0 README.md
  2. +1 −0 lib/sinatra/contrib.rb
  3. +81 −0 lib/sinatra/multi_route.rb
  4. +4 −1 lib/sinatra/reloader.rb
  5. +45 −0 spec/multi_route_spec.rb
View
@@ -39,6 +39,9 @@ Currently included:
corresponding `Link` HTTP headers. Adds `link`, `stylesheet` and `prefetch`
helper methods.
+* `sinatra/multi_route`: Adds ability to define one route block for multiple
+ routes and multiple or custom HTTP verbs.
+
* `sinatra/namespace`: Adds namespace support to Sinatra.
* `sinatra/respond_with`: Choose action and/or template depending automatically
@@ -8,6 +8,7 @@ module Contrib
# Sinatra::Application by default.
module Common
register :ConfigFile
+ register :MultiRoute
register :Namespace
register :RespondWith
@@ -0,0 +1,81 @@
+require 'sinatra/base'
+
+module Sinatra
+ # = Sinatra::MultiRoute
+ #
+ # Create multiple routes with one statement.
+ #
+ # == Usage
+ #
+ # Use this extension to create a handler for multiple routes:
+ #
+ # get '/foo', '/bar' do
+ # # ...
+ # end
+ #
+ # Or for multiple verbs:
+ #
+ # route :get, :post, '/' do
+ # # ...
+ # end
+ #
+ # Or even for custom verbs:
+ #
+ # route 'LIST', '/' do
+ # # ...
+ # end
+ #
+ # === Classic Application
+ #
+ # To use the extension in a classic application all you need to do is require
+ # it:
+ #
+ # require "sinatra"
+ # require "sinatra/multi_route"
+ #
+ # # Your classic application code goes here...
+ #
+ # === Modular Application
+ #
+ # To use the extension in a modular application you need to require it, and
+ # then, tell the application you will use it:
+ #
+ # require "sinatra/base"
+ # require "sinatra/multi_route"
+ #
+ # class MyApp < Sinatra::Base
+ # register Sinatra::MultiRoute
+ #
+ # # The rest of your modular application code goes here...
+ # end
+ #
+ module MultiRoute
+ def head(*args, &block) super(*route_args(args), &block) end
+ def delete(*args, &block) super(*route_args(args), &block) end
+ def get(*args, &block) super(*route_args(args), &block) end
+ def options(*args, &block) super(*route_args(args), &block) end
+ def patch(*args, &block) super(*route_args(args), &block) end
+ def post(*args, &block) super(*route_args(args), &block) end
+ def put(*args, &block) super(*route_args(args), &block) end
+
+ def route(*args, &block)
+ options = Hash === args.last ? args.pop : {}
+ routes = [*args.pop]
+ args.each do |verb|
+ verb = verb.to_s.upcase if Symbol === verb
+ routes.each do |route|
+ super(verb, route, options, &block)
+ end
+ end
+ end
+
+ private
+
+ def route_args(args)
+ options = Hash === args.last ? args.pop : {}
+ [args, options]
+ end
+ end
+
+ register MultiRoute
+end
@@ -234,7 +234,10 @@ module BaseMethods
# Does everything Sinatra::Base#route does, but it also tells the
# +Watcher::List+ for the Sinatra application to watch the defined
# route.
- def route(verb, path, options={}, &block)
+ #
+ # Note: We are using #compile! so we don't interfere with extensions
+ # changing #route.
+ def compile!(verb, path, block, options = {})
source_location = block.respond_to?(:source_location) ?
block.source_location.first : caller_files[1]
signature = super
@@ -0,0 +1,45 @@
+require 'backports'
+require_relative 'spec_helper'
+
+describe Sinatra::MultiRoute do
+ before do
+ count = 0
+ mock_app do
+ set(:some_condition) { count += 1 }
+ register Sinatra::MultiRoute
+ get('/') { 'normal' }
+ get('/foo', '/bar', :some_condition => true) { 'paths' }
+ route('PUT', 'POST', '/') { 'verb' }
+ route(:get, '/baz') { 'symbol as verb' }
+ end
+ @count = count
+ end
+
+ it 'does still allow normal routing' do
+ get('/').should be_ok
+ body.should be == 'normal'
+ end
+
+ it 'supports multpile routes' do
+ get('/foo').should be_ok
+ body.should be == 'paths'
+ get('/bar').should be_ok
+ body.should be == 'paths'
+ end
+
+ it 'triggers conditions' do
+ @count.should be == 4
+ end
+
+ it 'supports multpile verbs' do
+ post('/').should be_ok
+ body.should be == 'verb'
+ put('/').should be_ok
+ body.should be == 'verb'
+ end
+
+ it 'takes symbols as verbs' do
+ get('/baz').should be_ok
+ body.should be == 'symbol as verb'
+ end
+end

2 comments on commit 12b184d

@ryansobol

+1 for the multi route syntax

@davidsoncasey

This is great. Exactly what I was hoping to find.

Please sign in to comment.