6 Result = Struct.new(:body, :params)
10 URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR)
11 PARAM = /:(#{URI_CHAR}+)/.freeze unless defined?(PARAM)
13 attr_reader :path, :block, :param_keys, :pattern
15 def initialize(path, &b)
19 regex = @path.to_s.gsub(PARAM) do
20 @param_keys << $1.intern
23 @pattern = /^#{regex}$/
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)
39 @events = Hash.new { |hash, key| hash[key] = [] }
42 def define_event(method, path, &b)
43 events[method] << event = Event.new(path, &b)
48 events[env['REQUEST_METHOD'].downcase.to_sym].eject(&[:invoke, env])
58 old_verbose, $VERBOSE = $VERBOSE, nil
61 $VERBOSE = old_verbose
68 # Converts +self+ to an escaped URI parameter value
69 # 'Foo Bar'.to_param # => 'Foo%20Bar'
74 # Converts +self+ from an escaped URI parameter value
75 # 'Foo%20Bar'.from_param # => 'Foo Bar'
85 map { |k,v| "#{k}=#{URI.escape(v)}" }.join('&')
89 self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
93 reject { |k,v| !keys.include?(k) }
101 Proc.new { |*args| args.shift.__send__(self, *args) }
109 self.inject({}) { |h, (k, v)| h[k] = v; h }
113 Proc.new { |*args| args.shift.__send__(self[0], *(args + self[1..-1])) }
121 find { |e| result = block[e] and break result }