more tests
[sinatra.git] / lib / sinatra.rb
blobbf47c1d6384795d8764a2f67b3a91e97d2dfa12f
1 require 'rubygems'
2 require 'rack'
4 module Sinatra
6   Result = Struct.new(:body, :params)
7   
8   class Event
10     URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR)
11     PARAM = /:(#{URI_CHAR}+)/.freeze unless defined?(PARAM)
12     
13     attr_reader :path, :block, :param_keys, :pattern
14     
15     def initialize(path, &b)
16       @path = path
17       @block = b
18       @param_keys = []
19       regex = @path.to_s.gsub(PARAM) do
20         @param_keys << $1.intern
21         "(#{URI_CHAR}+)"
22       end
23       @pattern = /^#{regex}$/
24     end
25         
26     def invoke(env)
27       return unless pattern =~ env['PATH_INFO'].squeeze('/')
28       params = param_keys.zip($~.captures.map(&:from_param)).to_hash
29       Result.new(block.call, params)
30     end
31     
32   end
33   
34   class Application
35     
36     attr_reader :events
37     
38     def initialize
39       @events = Hash.new { |hash, key| hash[key] = [] }
40     end
41     
42     def define_event(method, path, &b)
43       events[method] << event = Event.new(path, &b)
44       event
45     end
46     
47     def lookup(env)
48       events[env['REQUEST_METHOD'].downcase.to_sym].eject(&[:invoke, env])
49     end
50     
51   end
52   
53 end
55 module Kernel
57   def silence_warnings
58     old_verbose, $VERBOSE = $VERBOSE, nil
59     yield
60   ensure
61     $VERBOSE = old_verbose
62   end
64 end
66 class String
68   # Converts +self+ to an escaped URI parameter value
69   #   'Foo Bar'.to_param # => 'Foo%20Bar'
70   def to_param
71     URI.escape(self)
72   end
73   
74   # Converts +self+ from an escaped URI parameter value
75   #   'Foo%20Bar'.from_param # => 'Foo Bar'
76   def from_param
77     URI.unescape(self)
78   end
79   
80 end
82 class Hash
83   
84   def to_params
85     map { |k,v| "#{k}=#{URI.escape(v)}" }.join('&')
86   end
87   
88   def symbolize_keys
89     self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
90   end
91   
92   def pass(*keys)
93     reject { |k,v| !keys.include?(k) }
94   end
95   
96 end
98 class Symbol
99   
100   def to_proc 
101     Proc.new { |*args| args.shift.__send__(self, *args) }
102   end
103   
106 class Array
107   
108   def to_hash
109     self.inject({}) { |h, (k, v)|  h[k] = v; h }
110   end
111   
112   def to_proc
113     Proc.new { |*args| args.shift.__send__(self[0], *(args + self[1..-1])) }
114   end
115   
118 module Enumerable
119   
120   def eject(&block)
121     find { |e| result = block[e] and break result }
122   end
123