routes determined
[sinatra.git] / lib / sinatra.rb
blobd14fa7b6f8c136817e203021710258cf4951edbe
1 require "rubygems"
2 require "rack"
4 class String
5   def to_param
6     URI.escape(self)
7   end
8   
9   def from_param
10     URI.unescape(self)
11   end
12 end
14 class Symbol
15   def to_proc 
16     Proc.new { |*args| args.shift.__send__(self, *args) }
17   end
18 end
20 class Array
21   def to_hash
22     self.inject({}) { |h, (k, v)|  h[k] = v; h }
23   end
24   
25   def to_proc
26     Proc.new { |*args| args.shift.send(self[0], args + self[1..-1]) }
27   end
28 end
31 module Enumerable
32   def eject(&block)
33     find { |e| result = block[e] and break result }
34   end
35 end
38 module Sinatra
39   extend self
40   
41   def request_types
42     @request_types ||= [:get, :put, :post, :delete]
43   end
44   
45   def routes
46     @routes ||= Hash.new do |hash, key|
47       hash[key] = [] if request_types.include?(key)
48     end
49   end
50   
51   def determine_event(verb, path)
52     routes[verb].eject { |r| r.match(path) }
53   end
54   
55   class Route
56     
57     URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR)
58     PARAM = /:(#{URI_CHAR}+)/.freeze unless defined?(PARAM)
59     
60     attr_reader :block, :path
61     
62     def initialize(path, &b)
63       @path, @block = path, b
64       @param_keys = []
65       regex = path.to_s.gsub(PARAM) do
66         @param_keys << $1.intern
67         "(#{URI_CHAR}+)"
68       end
69       @pattern = /^#{regex}$/
70       @struct = Struct.new(:block, :params)
71     end
72     
73     def match(path)
74       return nil unless path =~ @pattern
75       params = @param_keys.zip($~.captures.map(&:from_param)).to_hash
76       @struct.new(@block, params)
77     end
78     
79   end
80   
81 end