sinatra-sinatra 0.9.0.4 → 0.9.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +1 -1
- data/CHANGES +44 -0
- data/README.rdoc +12 -0
- data/Rakefile +2 -1
- data/compat/app_test.rb +3 -2
- data/compat/compat_test.rb +12 -0
- data/lib/sinatra/base.rb +206 -114
- data/lib/sinatra/compat.rb +18 -16
- data/lib/sinatra/main.rb +4 -4
- data/lib/sinatra/test.rb +10 -8
- data/sinatra.gemspec +7 -2
- data/test/base_test.rb +13 -0
- data/test/extensions_test.rb +63 -0
- data/test/helper.rb +13 -2
- data/test/helpers_test.rb +58 -0
- data/test/mapped_error_test.rb +6 -6
- data/test/middleware_test.rb +3 -1
- data/test/response_test.rb +42 -0
- data/test/routing_test.rb +166 -0
- data/test/server_test.rb +41 -0
- data/test/static_test.rb +8 -10
- data/test/test_test.rb +21 -0
- metadata +11 -2
data/lib/sinatra/base.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
|
+
require 'thread'
|
1
2
|
require 'time'
|
2
3
|
require 'uri'
|
3
4
|
require 'rack'
|
4
5
|
require 'rack/builder'
|
5
6
|
|
6
7
|
module Sinatra
|
7
|
-
VERSION = '0.9.0.
|
8
|
+
VERSION = '0.9.0.5'
|
8
9
|
|
10
|
+
# The request object. See Rack::Request for more info:
|
11
|
+
# http://rack.rubyforge.org/doc/classes/Rack/Request.html
|
9
12
|
class Request < Rack::Request
|
10
13
|
def user_agent
|
11
14
|
@env['HTTP_USER_AGENT']
|
12
15
|
end
|
13
16
|
|
14
17
|
def accept
|
15
|
-
@env['HTTP_ACCEPT'].split(',').map { |a| a.strip }
|
18
|
+
@env['HTTP_ACCEPT'].to_s.split(',').map { |a| a.strip }
|
16
19
|
end
|
17
20
|
|
18
21
|
# Override Rack 0.9.x's #params implementation (see #72 in lighthouse)
|
@@ -23,6 +26,10 @@ module Sinatra
|
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
29
|
+
# The response object. See Rack::Response and Rack::ResponseHelpers for
|
30
|
+
# more info:
|
31
|
+
# http://rack.rubyforge.org/doc/classes/Rack/Response.html
|
32
|
+
# http://rack.rubyforge.org/doc/classes/Rack/Response/Helpers.html
|
26
33
|
class Response < Rack::Response
|
27
34
|
def initialize
|
28
35
|
@status, @body = 200, []
|
@@ -44,17 +51,18 @@ module Sinatra
|
|
44
51
|
body = [body] if body.respond_to? :to_str
|
45
52
|
if header["Content-Length"].nil? && body.respond_to?(:to_ary)
|
46
53
|
header["Content-Length"] = body.to_ary.
|
47
|
-
inject(0) { |len, part| len + part.
|
54
|
+
inject(0) { |len, part| len + part.bytesize }.to_s
|
48
55
|
end
|
49
56
|
[status.to_i, header.to_hash, body]
|
50
57
|
end
|
51
58
|
end
|
52
59
|
end
|
53
60
|
|
54
|
-
class NotFound < NameError
|
61
|
+
class NotFound < NameError #:nodoc:
|
55
62
|
def code ; 404 ; end
|
56
63
|
end
|
57
64
|
|
65
|
+
# Methods available to routes, before filters, and views.
|
58
66
|
module Helpers
|
59
67
|
# Set or retrieve the response status code.
|
60
68
|
def status(value=nil)
|
@@ -82,7 +90,7 @@ module Sinatra
|
|
82
90
|
|
83
91
|
# Halt processing and return the error status provided.
|
84
92
|
def error(code, body=nil)
|
85
|
-
code, body
|
93
|
+
code, body = 500, code.to_str if code.respond_to? :to_str
|
86
94
|
response.body = body unless body.nil?
|
87
95
|
halt code
|
88
96
|
end
|
@@ -194,11 +202,42 @@ module Sinatra
|
|
194
202
|
halt 304 if etags.include?(value) || etags.include?('*')
|
195
203
|
end
|
196
204
|
end
|
205
|
+
|
206
|
+
## Sugar for redirect (example: redirect back)
|
207
|
+
def back ; request.referer ; end
|
208
|
+
|
197
209
|
end
|
198
210
|
|
211
|
+
# Template rendering methods. Each method takes a the name of a template
|
212
|
+
# to render as a Symbol and returns a String with the rendered output.
|
199
213
|
module Templates
|
200
|
-
def
|
201
|
-
|
214
|
+
def erb(template, options={})
|
215
|
+
require 'erb' unless defined? ::ERB
|
216
|
+
render :erb, template, options
|
217
|
+
end
|
218
|
+
|
219
|
+
def haml(template, options={})
|
220
|
+
require 'haml' unless defined? ::Haml
|
221
|
+
options[:options] ||= self.class.haml if self.class.respond_to? :haml
|
222
|
+
render :haml, template, options
|
223
|
+
end
|
224
|
+
|
225
|
+
def sass(template, options={}, &block)
|
226
|
+
require 'sass' unless defined? ::Sass
|
227
|
+
options[:layout] = false
|
228
|
+
render :sass, template, options
|
229
|
+
end
|
230
|
+
|
231
|
+
def builder(template=nil, options={}, &block)
|
232
|
+
require 'builder' unless defined? ::Builder
|
233
|
+
options, template = template, nil if template.is_a?(Hash)
|
234
|
+
template = lambda { block } if template.nil?
|
235
|
+
render :builder, template, options
|
236
|
+
end
|
237
|
+
|
238
|
+
private
|
239
|
+
def render(engine, template, options={}) #:nodoc:
|
240
|
+
data = lookup_template(engine, template, options)
|
202
241
|
output = __send__("render_#{engine}", template, data, options)
|
203
242
|
layout, data = lookup_layout(engine, options)
|
204
243
|
if layout
|
@@ -229,7 +268,7 @@ module Sinatra
|
|
229
268
|
return if options[:layout] == false
|
230
269
|
options.delete(:layout) if options[:layout] == true
|
231
270
|
template = options[:layout] || :layout
|
232
|
-
data
|
271
|
+
data = lookup_template(engine, template, options)
|
233
272
|
[template, data]
|
234
273
|
rescue Errno::ENOENT
|
235
274
|
nil
|
@@ -241,11 +280,6 @@ module Sinatra
|
|
241
280
|
"#{views_dir}/#{template}.#{engine}"
|
242
281
|
end
|
243
282
|
|
244
|
-
def erb(template, options={})
|
245
|
-
require 'erb' unless defined? ::ERB
|
246
|
-
render :erb, template, options
|
247
|
-
end
|
248
|
-
|
249
283
|
def render_erb(template, data, options, &block)
|
250
284
|
data = data.call if data.kind_of? Proc
|
251
285
|
instance = ::ERB.new(data)
|
@@ -253,13 +287,6 @@ module Sinatra
|
|
253
287
|
locals_assigns = locals.to_a.collect { |k,v| "#{k} = locals[:#{k}]" }
|
254
288
|
src = "#{locals_assigns.join("\n")}\n#{instance.src}"
|
255
289
|
eval src, binding, '(__ERB__)', locals_assigns.length + 1
|
256
|
-
instance.result(binding)
|
257
|
-
end
|
258
|
-
|
259
|
-
def haml(template, options={})
|
260
|
-
require 'haml' unless defined? ::Haml
|
261
|
-
options[:options] ||= self.class.haml if self.class.respond_to? :haml
|
262
|
-
render :haml, template, options
|
263
290
|
end
|
264
291
|
|
265
292
|
def render_haml(template, data, options, &block)
|
@@ -267,24 +294,11 @@ module Sinatra
|
|
267
294
|
engine.render(self, options[:locals] || {}, &block)
|
268
295
|
end
|
269
296
|
|
270
|
-
def sass(template, options={}, &block)
|
271
|
-
require 'sass' unless defined? ::Sass
|
272
|
-
options[:layout] = false
|
273
|
-
render :sass, template, options
|
274
|
-
end
|
275
|
-
|
276
297
|
def render_sass(template, data, options, &block)
|
277
298
|
engine = ::Sass::Engine.new(data, options[:sass] || {})
|
278
299
|
engine.render
|
279
300
|
end
|
280
301
|
|
281
|
-
def builder(template=nil, options={}, &block)
|
282
|
-
require 'builder' unless defined? ::Builder
|
283
|
-
options, template = template, nil if template.is_a?(Hash)
|
284
|
-
template = lambda { block } if template.nil?
|
285
|
-
render :builder, template, options
|
286
|
-
end
|
287
|
-
|
288
302
|
def render_builder(template, data, options, &block)
|
289
303
|
xml = ::Builder::XmlMarkup.new(:indent => 2)
|
290
304
|
if data.respond_to?(:to_str)
|
@@ -294,9 +308,9 @@ module Sinatra
|
|
294
308
|
end
|
295
309
|
xml.target!
|
296
310
|
end
|
297
|
-
|
298
311
|
end
|
299
312
|
|
313
|
+
# Base class for all Sinatra applications and middleware.
|
300
314
|
class Base
|
301
315
|
include Rack::Utils
|
302
316
|
include Helpers
|
@@ -309,6 +323,7 @@ module Sinatra
|
|
309
323
|
yield self if block_given?
|
310
324
|
end
|
311
325
|
|
326
|
+
# Rack call interface.
|
312
327
|
def call(env)
|
313
328
|
dup.call!(env)
|
314
329
|
end
|
@@ -324,19 +339,24 @@ module Sinatra
|
|
324
339
|
invoke { dispatch! }
|
325
340
|
invoke { error_block!(response.status) }
|
326
341
|
|
342
|
+
# never respond with a body on HEAD requests
|
327
343
|
@response.body = [] if @env['REQUEST_METHOD'] == 'HEAD'
|
344
|
+
|
328
345
|
@response.finish
|
329
346
|
end
|
330
347
|
|
348
|
+
# Access options defined with Base.set.
|
331
349
|
def options
|
332
350
|
self.class
|
333
351
|
end
|
334
352
|
|
353
|
+
# Exit the current block and halt the response.
|
335
354
|
def halt(*response)
|
336
355
|
response = response.first if response.length == 1
|
337
356
|
throw :halt, response
|
338
357
|
end
|
339
358
|
|
359
|
+
# Pass control to the next matching route.
|
340
360
|
def pass
|
341
361
|
throw :pass
|
342
362
|
end
|
@@ -352,7 +372,7 @@ module Sinatra
|
|
352
372
|
# routes
|
353
373
|
if routes = self.class.routes[@request.request_method]
|
354
374
|
original_params = @params
|
355
|
-
path
|
375
|
+
path = @request.path_info
|
356
376
|
|
357
377
|
routes.each do |pattern, keys, conditions, block|
|
358
378
|
if match = pattern.match(path)
|
@@ -373,6 +393,7 @@ module Sinatra
|
|
373
393
|
{}
|
374
394
|
end
|
375
395
|
@params = original_params.merge(params)
|
396
|
+
@block_params = values
|
376
397
|
|
377
398
|
catch(:pass) do
|
378
399
|
conditions.each { |cond|
|
@@ -389,10 +410,10 @@ module Sinatra
|
|
389
410
|
def nested_params(params)
|
390
411
|
return indifferent_hash.merge(params) if !params.keys.join.include?('[')
|
391
412
|
params.inject indifferent_hash do |res, (key,val)|
|
392
|
-
if key
|
393
|
-
|
394
|
-
|
395
|
-
head.inject(res){ |
|
413
|
+
if key.include?('[')
|
414
|
+
head = key.split(/[\]\[]+/)
|
415
|
+
last = head.pop
|
416
|
+
head.inject(res){ |hash,k| hash[k] ||= indifferent_hash }[last] = val
|
396
417
|
else
|
397
418
|
res[key] = val
|
398
419
|
end
|
@@ -421,7 +442,7 @@ module Sinatra
|
|
421
442
|
headers.each { |k, v| @response.headers[k] = v } if headers
|
422
443
|
elsif res.length == 2
|
423
444
|
@response.status = res.first
|
424
|
-
@response.body
|
445
|
+
@response.body = res.last
|
425
446
|
else
|
426
447
|
raise TypeError, "#{res.inspect} not supported"
|
427
448
|
end
|
@@ -441,21 +462,24 @@ module Sinatra
|
|
441
462
|
def dispatch!
|
442
463
|
route!
|
443
464
|
rescue NotFound => boom
|
465
|
+
handle_not_found!(boom)
|
466
|
+
rescue ::Exception => boom
|
467
|
+
handle_exception!(boom)
|
468
|
+
end
|
469
|
+
|
470
|
+
def handle_not_found!(boom)
|
444
471
|
@env['sinatra.error'] = boom
|
445
|
-
@response.status
|
446
|
-
@response.body
|
472
|
+
@response.status = 404
|
473
|
+
@response.body = ['<h1>Not Found</h1>']
|
447
474
|
error_block! boom.class, NotFound
|
475
|
+
end
|
448
476
|
|
449
|
-
|
477
|
+
def handle_exception!(boom)
|
450
478
|
@env['sinatra.error'] = boom
|
451
479
|
|
452
|
-
if options.dump_errors?
|
453
|
-
|
454
|
-
msg = ["#{boom.class} - #{boom.message}:", *backtrace].join("\n ")
|
455
|
-
@env['rack.errors'].write(msg)
|
456
|
-
end
|
480
|
+
dump_errors!(boom) if options.dump_errors?
|
481
|
+
raise boom if options.raise_errors?
|
457
482
|
|
458
|
-
raise boom if options.raise_errors?
|
459
483
|
@response.status = 500
|
460
484
|
error_block! boom.class, Exception
|
461
485
|
end
|
@@ -472,6 +496,13 @@ module Sinatra
|
|
472
496
|
nil
|
473
497
|
end
|
474
498
|
|
499
|
+
def dump_errors!(boom)
|
500
|
+
backtrace = clean_backtrace(boom.backtrace)
|
501
|
+
msg = ["#{boom.class} - #{boom.message}:",
|
502
|
+
*backtrace].join("\n ")
|
503
|
+
@env['rack.errors'].write(msg)
|
504
|
+
end
|
505
|
+
|
475
506
|
def clean_backtrace(trace)
|
476
507
|
return trace unless options.clean_trace?
|
477
508
|
|
@@ -493,13 +524,14 @@ module Sinatra
|
|
493
524
|
attr_accessor :routes, :filters, :conditions, :templates,
|
494
525
|
:middleware, :errors
|
495
526
|
|
527
|
+
public
|
496
528
|
def set(option, value=self)
|
497
529
|
if value.kind_of?(Proc)
|
498
530
|
metadef(option, &value)
|
499
531
|
metadef("#{option}?") { !!__send__(option) }
|
500
532
|
metadef("#{option}=") { |val| set(option, Proc.new{val}) }
|
501
533
|
elsif value == self && option.respond_to?(:to_hash)
|
502
|
-
option.to_hash.each(
|
534
|
+
option.to_hash.each { |k,v| set(k, v) }
|
503
535
|
elsif respond_to?("#{option}=")
|
504
536
|
__send__ "#{option}=", value
|
505
537
|
else
|
@@ -537,14 +569,10 @@ module Sinatra
|
|
537
569
|
end
|
538
570
|
|
539
571
|
def use_in_file_templates!
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
/rubygems\/custom_require\.rb/
|
545
|
-
].all? { |x| s !~ x }
|
546
|
-
end
|
547
|
-
file = line.sub(/:\d+.*$/, '')
|
572
|
+
ignore = [/lib\/sinatra.*\.rb/, /\(.*\)/, /rubygems\/custom_require\.rb/]
|
573
|
+
file = caller.
|
574
|
+
map { |line| line.sub(/:\d+.*$/, '') }.
|
575
|
+
find { |line| ignore.all? { |pattern| line !~ pattern } }
|
548
576
|
if data = ::IO.read(file).split('__END__')[1]
|
549
577
|
data.gsub!(/\r\n/, "\n")
|
550
578
|
template = nil
|
@@ -573,6 +601,7 @@ module Sinatra
|
|
573
601
|
@conditions << block
|
574
602
|
end
|
575
603
|
|
604
|
+
private
|
576
605
|
def host_name(pattern)
|
577
606
|
condition { pattern === request.host }
|
578
607
|
end
|
@@ -603,6 +632,7 @@ module Sinatra
|
|
603
632
|
}
|
604
633
|
end
|
605
634
|
|
635
|
+
public
|
606
636
|
def get(path, opts={}, &block)
|
607
637
|
conditions = @conditions.dup
|
608
638
|
route('GET', path, opts, &block)
|
@@ -627,7 +657,12 @@ module Sinatra
|
|
627
657
|
|
628
658
|
define_method "#{verb} #{path}", &block
|
629
659
|
unbound_method = instance_method("#{verb} #{path}")
|
630
|
-
block =
|
660
|
+
block =
|
661
|
+
if block.arity != 0
|
662
|
+
lambda { unbound_method.bind(self).call(*@block_params) }
|
663
|
+
else
|
664
|
+
lambda { unbound_method.bind(self).call }
|
665
|
+
end
|
631
666
|
|
632
667
|
(routes[verb] ||= []).
|
633
668
|
push([pattern, keys, conditions, block]).last
|
@@ -659,11 +694,22 @@ module Sinatra
|
|
659
694
|
end
|
660
695
|
|
661
696
|
public
|
697
|
+
def helpers(*extensions, &block)
|
698
|
+
class_eval(&block) if block_given?
|
699
|
+
include *extensions
|
700
|
+
end
|
701
|
+
|
702
|
+
def register(*extensions, &block)
|
703
|
+
extensions << Module.new(&block) if block
|
704
|
+
extend *extensions
|
705
|
+
end
|
706
|
+
|
662
707
|
def development? ; environment == :development ; end
|
663
708
|
def test? ; environment == :test ; end
|
664
709
|
def production? ; environment == :production ; end
|
665
710
|
|
666
711
|
def configure(*envs, &block)
|
712
|
+
return if reloading?
|
667
713
|
yield if envs.empty? || envs.include?(environment.to_sym)
|
668
714
|
end
|
669
715
|
|
@@ -674,7 +720,7 @@ module Sinatra
|
|
674
720
|
|
675
721
|
def run!(options={})
|
676
722
|
set options
|
677
|
-
handler
|
723
|
+
handler = detect_rack_handler
|
678
724
|
handler_name = handler.name.gsub(/.*::/, '')
|
679
725
|
puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
|
680
726
|
"on #{port} for #{environment} with backup from #{handler_name}"
|
@@ -690,8 +736,19 @@ module Sinatra
|
|
690
736
|
end
|
691
737
|
|
692
738
|
def call(env)
|
693
|
-
|
694
|
-
|
739
|
+
synchronize do
|
740
|
+
reload! if reload?
|
741
|
+
construct_middleware if @callsite.nil?
|
742
|
+
@callsite.call(env)
|
743
|
+
end
|
744
|
+
end
|
745
|
+
|
746
|
+
def reload!
|
747
|
+
@reloading = true
|
748
|
+
superclass.send :reset!, self
|
749
|
+
$LOADED_FEATURES.delete("sinatra.rb")
|
750
|
+
::Kernel.load app_file
|
751
|
+
@reloading = false
|
695
752
|
end
|
696
753
|
|
697
754
|
private
|
@@ -720,17 +777,34 @@ module Sinatra
|
|
720
777
|
@callsite = nil
|
721
778
|
end
|
722
779
|
|
723
|
-
def
|
724
|
-
subclass.routes
|
725
|
-
subclass.templates
|
780
|
+
def reset!(subclass = self)
|
781
|
+
subclass.routes = dupe_routes
|
782
|
+
subclass.templates = templates.dup
|
726
783
|
subclass.conditions = []
|
727
|
-
subclass.filters
|
728
|
-
subclass.errors
|
784
|
+
subclass.filters = filters.dup
|
785
|
+
subclass.errors = errors.dup
|
729
786
|
subclass.middleware = middleware.dup
|
730
787
|
subclass.send :reset_middleware
|
788
|
+
end
|
789
|
+
|
790
|
+
def inherited(subclass)
|
791
|
+
reset!(subclass)
|
731
792
|
super
|
732
793
|
end
|
733
794
|
|
795
|
+
def reloading?
|
796
|
+
@reloading ||= false
|
797
|
+
end
|
798
|
+
|
799
|
+
@@mutex = Mutex.new
|
800
|
+
def synchronize(&block)
|
801
|
+
if lock?
|
802
|
+
@@mutex.synchronize(&block)
|
803
|
+
else
|
804
|
+
yield
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
734
808
|
def dupe_routes
|
735
809
|
routes.inject({}) do |hash,(request_method,routes)|
|
736
810
|
hash[request_method] = routes.dup
|
@@ -762,6 +836,8 @@ module Sinatra
|
|
762
836
|
set :root, Proc.new { app_file && File.expand_path(File.dirname(app_file)) }
|
763
837
|
set :views, Proc.new { root && File.join(root, 'views') }
|
764
838
|
set :public, Proc.new { root && File.join(root, 'public') }
|
839
|
+
set :reload, Proc.new { app_file? && app_file !~ /\.ru$/i && development? }
|
840
|
+
set :lock, Proc.new { reload? }
|
765
841
|
|
766
842
|
# static files route
|
767
843
|
get(/.*[^\/]$/) do
|
@@ -838,6 +914,7 @@ module Sinatra
|
|
838
914
|
end
|
839
915
|
end
|
840
916
|
|
917
|
+
# Base class for classic style (top-level) applications.
|
841
918
|
class Default < Base
|
842
919
|
set :raise_errors, false
|
843
920
|
set :dump_errors, true
|
@@ -846,61 +923,35 @@ module Sinatra
|
|
846
923
|
set :methodoverride, true
|
847
924
|
set :static, true
|
848
925
|
set :run, false
|
849
|
-
set :reload, Proc.new { app_file? && app_file !~ /\.ru$/i && development? }
|
850
|
-
set :lock, Proc.new { reload? }
|
851
|
-
|
852
|
-
def self.reloading?
|
853
|
-
@reloading ||= false
|
854
|
-
end
|
855
|
-
|
856
|
-
def self.configure(*envs)
|
857
|
-
super unless reloading?
|
858
|
-
end
|
859
|
-
|
860
|
-
def self.call(env)
|
861
|
-
synchronize do
|
862
|
-
reload! if reload?
|
863
|
-
super
|
864
|
-
end
|
865
|
-
end
|
866
|
-
|
867
|
-
def self.reload!
|
868
|
-
@reloading = true
|
869
|
-
superclass.send :inherited, self
|
870
|
-
$LOADED_FEATURES.delete("sinatra.rb")
|
871
|
-
::Kernel.load app_file
|
872
|
-
@reloading = false
|
873
|
-
end
|
874
926
|
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
@@mutex.synchronize(&block)
|
880
|
-
else
|
881
|
-
yield
|
882
|
-
end
|
927
|
+
def self.register(*extensions, &block) #:nodoc:
|
928
|
+
added_methods = extensions.map {|m| m.public_instance_methods }.flatten
|
929
|
+
Delegator.delegate *added_methods
|
930
|
+
super(*extensions, &block)
|
883
931
|
end
|
884
932
|
end
|
885
933
|
|
934
|
+
# The top-level Application. All DSL methods executed on main are delegated
|
935
|
+
# to this class.
|
886
936
|
class Application < Default
|
887
937
|
end
|
888
938
|
|
889
|
-
module Delegator
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
::Sinatra::Application.#{method_name}(*args, &b)
|
900
|
-
end
|
901
|
-
private :#{method_name}
|
902
|
-
RUBY
|
939
|
+
module Delegator #:nodoc:
|
940
|
+
def self.delegate(*methods)
|
941
|
+
methods.each do |method_name|
|
942
|
+
eval <<-RUBY, binding, '(__DELEGATE__)', 1
|
943
|
+
def #{method_name}(*args, &b)
|
944
|
+
::Sinatra::Application.#{method_name}(*args, &b)
|
945
|
+
end
|
946
|
+
private :#{method_name}
|
947
|
+
RUBY
|
948
|
+
end
|
903
949
|
end
|
950
|
+
|
951
|
+
delegate :get, :put, :post, :delete, :head, :template, :layout, :before,
|
952
|
+
:error, :not_found, :configures, :configure, :set, :set_option,
|
953
|
+
:set_options, :enable, :disable, :use, :development?, :test?,
|
954
|
+
:production?, :use_in_file_templates!, :helpers
|
904
955
|
end
|
905
956
|
|
906
957
|
def self.new(base=Base, options={}, &block)
|
@@ -908,4 +959,45 @@ module Sinatra
|
|
908
959
|
base.send :class_eval, &block if block_given?
|
909
960
|
base
|
910
961
|
end
|
962
|
+
|
963
|
+
# Extend the top-level DSL with the modules provided.
|
964
|
+
def self.register(*extensions, &block)
|
965
|
+
Default.register(*extensions, &block)
|
966
|
+
end
|
967
|
+
|
968
|
+
# Include the helper modules provided in Sinatra's request context.
|
969
|
+
def self.helpers(*extensions, &block)
|
970
|
+
Default.helpers(*extensions, &block)
|
971
|
+
end
|
972
|
+
end
|
973
|
+
|
974
|
+
class String #:nodoc:
|
975
|
+
# Define String#each under 1.9 for Rack compatibility. This should be
|
976
|
+
# removed once Rack is fully 1.9 compatible.
|
977
|
+
alias_method :each, :each_line unless ''.respond_to? :each
|
978
|
+
|
979
|
+
# Define String#bytesize as an alias to String#length for Ruby 1.8.6 and
|
980
|
+
# earlier.
|
981
|
+
alias_method :bytesize, :length unless ''.respond_to? :bytesize
|
982
|
+
end
|
983
|
+
|
984
|
+
class Rack::Builder
|
985
|
+
## Sugar to include a classic style app in a rackup.
|
986
|
+
##
|
987
|
+
## This will eval the source into a Sinatra::Default class
|
988
|
+
## Example:
|
989
|
+
##
|
990
|
+
## require 'sinatra/base'
|
991
|
+
##
|
992
|
+
## map '/foo' do
|
993
|
+
## run Sinatra("foo.rb")
|
994
|
+
## end
|
995
|
+
##
|
996
|
+
## run Sinatra("bar.rb")
|
997
|
+
##
|
998
|
+
def Sinatra(file, base=Sinatra::Default)
|
999
|
+
Sinatra.new(base) {
|
1000
|
+
expanded = File.expand_path(file)
|
1001
|
+
self.class_eval(File.read(expanded), expanded) }
|
1002
|
+
end
|
911
1003
|
end
|
data/lib/sinatra/compat.rb
CHANGED
@@ -9,7 +9,7 @@ require 'sinatra/base'
|
|
9
9
|
require 'sinatra/main'
|
10
10
|
|
11
11
|
# Like Kernel#warn but outputs the location that triggered the warning.
|
12
|
-
def sinatra_warn(*message)
|
12
|
+
def sinatra_warn(*message) #:nodoc:
|
13
13
|
line = caller.
|
14
14
|
detect { |line| line !~ /(?:lib\/sinatra\/|__DELEGATE__)/ }.
|
15
15
|
sub(/:in .*/, '')
|
@@ -34,25 +34,27 @@ end
|
|
34
34
|
# technically a Sinatra issue but many Sinatra apps access the old
|
35
35
|
# MIME_TYPES constants due to Sinatra example code.
|
36
36
|
require 'rack/file'
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
37
|
+
module Rack #:nodoc:
|
38
|
+
class File #:nodoc:
|
39
|
+
def self.const_missing(const_name)
|
40
|
+
if const_name == :MIME_TYPES
|
41
|
+
hash = Hash.new { |hash,key| Rack::Mime::MIME_TYPES[".#{key}"] }
|
42
|
+
const_set :MIME_TYPES, hash
|
43
|
+
sinatra_warn 'Rack::File::MIME_TYPES is deprecated; use Rack::Mime instead.'
|
44
|
+
hash
|
45
|
+
else
|
46
|
+
super
|
47
|
+
end
|
46
48
|
end
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
52
|
module Sinatra
|
51
|
-
module Compat
|
53
|
+
module Compat #:nodoc:
|
52
54
|
end
|
53
55
|
|
54
56
|
# Make Sinatra::EventContext an alias for Sinatra::Default to unbreak plugins.
|
55
|
-
def self.const_missing(const_name)
|
57
|
+
def self.const_missing(const_name) #:nodoc:
|
56
58
|
if const_name == :EventContext
|
57
59
|
const_set :EventContext, Sinatra::Default
|
58
60
|
sinatra_warn 'Sinatra::EventContext is deprecated; use Sinatra::Default instead.'
|
@@ -73,7 +75,7 @@ module Sinatra
|
|
73
75
|
end
|
74
76
|
|
75
77
|
class Default < Base
|
76
|
-
def self.const_missing(const_name)
|
78
|
+
def self.const_missing(const_name) #:nodoc:
|
77
79
|
if const_name == :FORWARD_METHODS
|
78
80
|
sinatra_warn 'Sinatra::Application::FORWARD_METHODS is deprecated;',
|
79
81
|
'use Sinatra::Delegator::METHODS instead.'
|
@@ -107,7 +109,7 @@ module Sinatra
|
|
107
109
|
# Throwing halt with a Symbol and the to_result convention are
|
108
110
|
# deprecated. Override the invoke method to detect those types of return
|
109
111
|
# values.
|
110
|
-
def invoke(&block)
|
112
|
+
def invoke(&block) #:nodoc:
|
111
113
|
res = super
|
112
114
|
case
|
113
115
|
when res.kind_of?(Symbol)
|
@@ -121,7 +123,7 @@ module Sinatra
|
|
121
123
|
res
|
122
124
|
end
|
123
125
|
|
124
|
-
def options
|
126
|
+
def options #:nodoc:
|
125
127
|
Options.new(self.class)
|
126
128
|
end
|
127
129
|
|
@@ -184,7 +186,7 @@ module Sinatra
|
|
184
186
|
end
|
185
187
|
|
186
188
|
# Deprecated. Missing messages are no longer delegated to @response.
|
187
|
-
def method_missing(name, *args, &b)
|
189
|
+
def method_missing(name, *args, &b) #:nodoc:
|
188
190
|
if @response.respond_to?(name)
|
189
191
|
sinatra_warn "The '#{name}' method is deprecated; use 'response.#{name}' instead."
|
190
192
|
@response.send(name, *args, &b)
|
data/lib/sinatra/main.rb
CHANGED
@@ -2,6 +2,10 @@ require 'sinatra/base'
|
|
2
2
|
|
3
3
|
module Sinatra
|
4
4
|
class Default < Base
|
5
|
+
|
6
|
+
# we assume that the first file that requires 'sinatra' is the
|
7
|
+
# app_file. all other path related options are calculated based
|
8
|
+
# on this path by default.
|
5
9
|
set :app_file, lambda {
|
6
10
|
ignore = [
|
7
11
|
/lib\/sinatra.*\.rb$/, # all sinatra code
|
@@ -32,10 +36,6 @@ end
|
|
32
36
|
|
33
37
|
include Sinatra::Delegator
|
34
38
|
|
35
|
-
def helpers(&block)
|
36
|
-
Sinatra::Application.send :class_eval, &block
|
37
|
-
end
|
38
|
-
|
39
39
|
def mime(ext, type)
|
40
40
|
ext = ".#{ext}" unless ext.to_s[0] == ?.
|
41
41
|
Rack::Mime::MIME_TYPES[ext.to_s] = type
|