5 def dslify_writter(*syms)
9 self.send "#{sym}=", v if v
20 Result = Struct.new(:block, :params)
23 @app ||= Application.new
32 URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR)
33 PARAM = /:(#{URI_CHAR}+)/.freeze unless defined?(PARAM)
35 attr_reader :path, :block, :param_keys, :pattern
37 def initialize(path, &b)
41 regex = @path.to_s.gsub(PARAM) do
42 @param_keys << $1.intern
45 @pattern = /^#{regex}$/
49 return unless pattern =~ env['PATH_INFO'].squeeze('/')
50 params = param_keys.zip($~.captures.map(&:from_param)).to_hash
51 Result.new(block, params)
58 module ResponseHelpers
61 throw :halt, NotFound.new(path)
66 include ResponseHelpers
68 attr_accessor :request, :response
70 dslify_writter :status, :body
72 def initialize(request, response, route_params)
75 @route_params = route_params
80 @params ||= @route_params.merge(@request.params).symbolize_keys
83 def complete(returned)
84 @response.body ||= returned
87 def method_missing(name, *args, &b)
88 @response.send(name, *args, &b)
98 def to_result(cx, *args)
100 cx.header.merge!('Location' => @path)
110 @events = Hash.new { |hash, key| hash[key] = [] }
113 def define_event(method, path, &b)
114 events[method] << event = Event.new(path, &b)
119 events[env['REQUEST_METHOD'].downcase.to_sym].eject(&[:invoke, env])
123 return [404, {}, 'Not Found'] unless result = lookup(env)
124 context = EventContext.new(
125 Rack::Request.new(env),
129 returned = catch(:halt) do
130 [:complete, context.instance_eval(&result.block)]
132 result = returned.to_result(context)
133 context.body = String === result ? [*result] : result
142 Sinatra.application.define_event(:get, path, &b)
146 Sinatra.application.define_event(:post, path, &b)
150 Sinatra.application.define_event(:put, path, &b)
154 Sinatra.application.define_event(:delete, path, &b)
158 Sinatra::EventContext.class_eval(&b)
161 ### Misc Core Extensions
166 old_verbose, $VERBOSE = $VERBOSE, nil
169 $VERBOSE = old_verbose
176 # Converts +self+ to an escaped URI parameter value
177 # 'Foo Bar'.to_param # => 'Foo%20Bar'
182 # Converts +self+ from an escaped URI parameter value
183 # 'Foo%20Bar'.from_param # => 'Foo Bar'
193 map { |k,v| "#{k}=#{URI.escape(v)}" }.join('&')
197 self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
201 reject { |k,v| !keys.include?(k) }
209 Proc.new { |*args| args.shift.__send__(self, *args) }
217 self.inject({}) { |h, (k, v)| h[k] = v; h }
221 Proc.new { |*args| args.shift.__send__(self[0], *(args + self[1..-1])) }
229 find { |e| result = block[e] and break result }
234 ### Core Extension results for throw :halt
237 def to_result(cx, *args)
238 cx.instance_eval(&self)
243 def to_result(cx, *args)
249 def to_result(cx, *args)
250 self.shift.to_result(cx, *self)
255 def to_result(cx, *args)
261 def to_result(cx, *args)