rtomayko-sinatra 0.9.0 → 0.9.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +40 -0
- data/CHANGES +189 -0
- data/README.rdoc +142 -95
- data/Rakefile +14 -49
- data/compat/events_test.rb +10 -7
- data/compat/helper.rb +13 -1
- data/lib/sinatra.rb +5 -0
- data/lib/sinatra/base.rb +138 -47
- data/lib/sinatra/compat.rb +142 -44
- data/lib/sinatra/test.rb +92 -91
- data/lib/sinatra/test/bacon.rb +17 -0
- data/lib/sinatra/test/rspec.rb +9 -0
- data/lib/sinatra/test/spec.rb +7 -0
- data/lib/sinatra/test/unit.rb +2 -2
- data/sinatra.gemspec +8 -5
- data/test/base_test.rb +33 -14
- data/test/builder_test.rb +12 -16
- data/test/erb_test.rb +11 -16
- data/test/filter_test.rb +48 -12
- data/test/haml_test.rb +14 -18
- data/test/helper.rb +25 -0
- data/test/helpers_test.rb +55 -62
- data/test/mapped_error_test.rb +43 -24
- data/test/middleware_test.rb +8 -13
- data/test/options_test.rb +29 -35
- data/test/reload_test.rb +16 -20
- data/test/request_test.rb +12 -5
- data/test/result_test.rb +16 -20
- data/test/routing_test.rb +150 -64
- data/test/sass_test.rb +8 -12
- data/test/sinatra_test.rb +2 -4
- data/test/static_test.rb +16 -19
- data/test/templates_test.rb +23 -19
- metadata +8 -6
- data/ChangeLog +0 -96
data/Rakefile
CHANGED
@@ -57,16 +57,17 @@ file package('.gem') => %w[dist/ sinatra.gemspec] + spec.files do |f|
|
|
57
57
|
end
|
58
58
|
|
59
59
|
file package('.tar.gz') => %w[dist/] + spec.files do |f|
|
60
|
-
sh
|
60
|
+
sh <<-SH
|
61
|
+
git archive \
|
62
|
+
--prefix=sinatra-#{source_version}/ \
|
63
|
+
--format=tar \
|
64
|
+
HEAD | gzip > #{f.name}
|
65
|
+
SH
|
61
66
|
end
|
62
67
|
|
63
68
|
# Rubyforge Release / Publish Tasks ==================================
|
64
69
|
|
65
|
-
desc 'Publish
|
66
|
-
task 'publish:doc' => 'doc/api/index.html' do
|
67
|
-
sh 'scp -rp doc/* rubyforge.org:/var/www/gforge-projects/sinatra/'
|
68
|
-
end
|
69
|
-
|
70
|
+
desc 'Publish gem and tarball to rubyforge'
|
70
71
|
task 'publish:gem' => [package('.gem'), package('.tar.gz')] do |t|
|
71
72
|
sh <<-end
|
72
73
|
rubyforge add_release sinatra sinatra #{spec.version} #{package('.gem')} &&
|
@@ -78,7 +79,7 @@ end
|
|
78
79
|
# Building docs requires HAML and the hanna gem:
|
79
80
|
# gem install mislav-hanna --source=http://gems.github.com
|
80
81
|
|
81
|
-
task 'doc' => ['doc:api'
|
82
|
+
task 'doc' => ['doc:api']
|
82
83
|
|
83
84
|
desc 'Generate Hanna RDoc under doc/api'
|
84
85
|
task 'doc:api' => ['doc/api/index.html']
|
@@ -104,47 +105,6 @@ def rdoc_to_html(file_name)
|
|
104
105
|
rdoc.convert(File.read(file_name))
|
105
106
|
end
|
106
107
|
|
107
|
-
def haml(locals={})
|
108
|
-
require 'haml'
|
109
|
-
template = File.read('doc/template.haml')
|
110
|
-
haml = Haml::Engine.new(template, :format => :html4, :attr_wrapper => '"')
|
111
|
-
haml.render(Object.new, locals)
|
112
|
-
end
|
113
|
-
|
114
|
-
desc 'Build website HTML and stuff'
|
115
|
-
task 'doc:site' => ['doc/index.html', 'doc/book.html']
|
116
|
-
|
117
|
-
file 'doc/index.html' => %w[README.rdoc doc/template.haml] do |file|
|
118
|
-
File.open(file.name, 'w') do |file|
|
119
|
-
file << haml(:title => 'Sinatra', :content => rdoc_to_html('README.rdoc'))
|
120
|
-
end
|
121
|
-
end
|
122
|
-
CLEAN.include 'doc/index.html'
|
123
|
-
|
124
|
-
file 'doc/book.html' => ['book/output/sinatra-book.html'] do |file|
|
125
|
-
File.open(file.name, 'w') do |file|
|
126
|
-
book_content = File.read('book/output/sinatra-book.html')
|
127
|
-
file << haml(:title => 'Sinatra Book', :content => book_content)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
CLEAN.include 'doc/book.html'
|
131
|
-
|
132
|
-
file 'book/output/sinatra-book.html' => FileList['book/**'] do |f|
|
133
|
-
unless File.directory?('book')
|
134
|
-
sh 'git clone git://github.com/cschneid/sinatra-book.git book'
|
135
|
-
end
|
136
|
-
sh((<<-SH).strip.gsub(/\s+/, ' '))
|
137
|
-
cd book &&
|
138
|
-
git fetch origin &&
|
139
|
-
git rebase origin/master &&
|
140
|
-
thor book:build
|
141
|
-
SH
|
142
|
-
end
|
143
|
-
CLEAN.include 'book/output/sinatra-book.html'
|
144
|
-
|
145
|
-
desc 'Build the Sinatra book'
|
146
|
-
task 'doc:book' => ['book/output/sinatra-book.html']
|
147
|
-
|
148
108
|
# Gemspec Helpers ====================================================
|
149
109
|
|
150
110
|
def source_version
|
@@ -152,7 +112,12 @@ def source_version
|
|
152
112
|
line.match(/.*VERSION = '(.*)'/)[1]
|
153
113
|
end
|
154
114
|
|
155
|
-
|
115
|
+
project_files =
|
116
|
+
FileList[
|
117
|
+
'{lib,test,compat,images}/**',
|
118
|
+
'Rakefile', 'CHANGES', 'README.rdoc'
|
119
|
+
]
|
120
|
+
file 'sinatra.gemspec' => project_files do |f|
|
156
121
|
# read spec file and split out manifest section
|
157
122
|
spec = File.read(f.name)
|
158
123
|
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
data/compat/events_test.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
2
|
|
3
3
|
context "Simple Events" do
|
4
|
-
|
5
4
|
def simple_request_hash(method, path)
|
6
5
|
Rack::Request.new({
|
7
6
|
'REQUEST_METHOD' => method.to_s.upcase,
|
@@ -14,16 +13,16 @@ context "Simple Events" do
|
|
14
13
|
|
15
14
|
def invoke_simple(path, request_path, &b)
|
16
15
|
params = nil
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
}
|
16
|
+
get path do
|
17
|
+
params = self.params
|
18
|
+
b.call if b
|
19
|
+
end
|
23
20
|
get_it request_path
|
24
21
|
MockResult.new(b, params)
|
25
22
|
end
|
26
23
|
|
24
|
+
setup { Sinatra.application = nil }
|
25
|
+
|
27
26
|
specify "return last value" do
|
28
27
|
block = Proc.new { 'Simple' }
|
29
28
|
result = invoke_simple('/', '/', &block)
|
@@ -38,6 +37,7 @@ context "Simple Events" do
|
|
38
37
|
result.params.should.equal "foo" => 'a', "bar" => 'b'
|
39
38
|
|
40
39
|
# unscapes
|
40
|
+
Sinatra.application = nil
|
41
41
|
result = invoke_simple('/:foo/:bar', '/a/blake%20mizerany')
|
42
42
|
result.should.not.be.nil
|
43
43
|
result.params.should.equal "foo" => 'a', "bar" => 'blake mizerany'
|
@@ -48,14 +48,17 @@ context "Simple Events" do
|
|
48
48
|
result.should.not.be.nil
|
49
49
|
result.params.should.equal "foo" => 'a', "bar" => 'b'
|
50
50
|
|
51
|
+
Sinatra.application = nil
|
51
52
|
result = invoke_simple('/?:foo?/?:bar?', '/a/')
|
52
53
|
result.should.not.be.nil
|
53
54
|
result.params.should.equal "foo" => 'a', "bar" => nil
|
54
55
|
|
56
|
+
Sinatra.application = nil
|
55
57
|
result = invoke_simple('/?:foo?/?:bar?', '/a')
|
56
58
|
result.should.not.be.nil
|
57
59
|
result.params.should.equal "foo" => 'a', "bar" => nil
|
58
60
|
|
61
|
+
Sinatra.application = nil
|
59
62
|
result = invoke_simple('/:foo?/?:bar?', '/')
|
60
63
|
result.should.not.be.nil
|
61
64
|
result.params.should.equal "foo" => nil, "bar" => nil
|
data/compat/helper.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'mocha'
|
3
3
|
|
4
|
+
# disable warnings in compat specs.
|
5
|
+
$VERBOSE = nil
|
6
|
+
|
4
7
|
$:.unshift File.dirname(File.dirname(__FILE__)) + "/lib"
|
5
8
|
|
6
9
|
ENV['RACK_ENV'] ||= 'test'
|
@@ -10,9 +13,18 @@ require 'sinatra/test'
|
|
10
13
|
require 'sinatra/test/unit'
|
11
14
|
require 'sinatra/test/spec'
|
12
15
|
|
16
|
+
module Sinatra::Test
|
17
|
+
# we need to remove the new test helper methods since they conflict with
|
18
|
+
# the top-level methods of the same name.
|
19
|
+
%w(get head post put delete).each do |verb|
|
20
|
+
remove_method verb
|
21
|
+
end
|
22
|
+
include Sinatra::Delegator
|
23
|
+
end
|
24
|
+
|
13
25
|
class Test::Unit::TestCase
|
26
|
+
include Sinatra::Test
|
14
27
|
def setup
|
15
28
|
@app = lambda { |env| Sinatra::Application.call(env) }
|
16
29
|
end
|
17
|
-
include Sinatra::Test
|
18
30
|
end
|
data/lib/sinatra.rb
CHANGED
data/lib/sinatra/base.rb
CHANGED
@@ -4,12 +4,23 @@ require 'rack'
|
|
4
4
|
require 'rack/builder'
|
5
5
|
|
6
6
|
module Sinatra
|
7
|
-
VERSION = '0.9.0'
|
7
|
+
VERSION = '0.9.0.2'
|
8
8
|
|
9
9
|
class Request < Rack::Request
|
10
10
|
def user_agent
|
11
11
|
@env['HTTP_USER_AGENT']
|
12
12
|
end
|
13
|
+
|
14
|
+
def accept
|
15
|
+
@env['HTTP_ACCEPT'].split(',').map { |a| a.strip }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Override Rack 0.9.x's #params implementation (see #72 in lighthouse)
|
19
|
+
def params
|
20
|
+
self.GET.update(self.POST)
|
21
|
+
rescue EOFError => boom
|
22
|
+
self.GET
|
23
|
+
end
|
13
24
|
end
|
14
25
|
|
15
26
|
class Response < Rack::Response
|
@@ -66,7 +77,7 @@ module Sinatra
|
|
66
77
|
def redirect(uri, *args)
|
67
78
|
status 302
|
68
79
|
response['Location'] = uri
|
69
|
-
halt
|
80
|
+
halt(*args)
|
70
81
|
end
|
71
82
|
|
72
83
|
# Halt processing and return the error status provided.
|
@@ -88,9 +99,7 @@ module Sinatra
|
|
88
99
|
|
89
100
|
# Look up a media type by file extension in Rack's mime registry.
|
90
101
|
def media_type(type)
|
91
|
-
|
92
|
-
type = ".#{type}" unless type.to_s[0] == ?.
|
93
|
-
Rack::Mime.mime_type(type, nil)
|
102
|
+
Base.media_type(type)
|
94
103
|
end
|
95
104
|
|
96
105
|
# Set the Content-Type of the response body given a media type or file
|
@@ -133,7 +142,7 @@ module Sinatra
|
|
133
142
|
class StaticFile < ::File #:nodoc:
|
134
143
|
alias_method :to_path, :path
|
135
144
|
def each
|
136
|
-
while buf = read(
|
145
|
+
while buf = read(8192)
|
137
146
|
yield buf
|
138
147
|
end
|
139
148
|
end
|
@@ -208,6 +217,7 @@ module Sinatra
|
|
208
217
|
|
209
218
|
def lookup_layout(engine, options)
|
210
219
|
return if options[:layout] == false
|
220
|
+
options.delete(:layout) if options[:layout] == true
|
211
221
|
template = options[:layout] || :layout
|
212
222
|
data = lookup_template(engine, template, options)
|
213
223
|
[template, data]
|
@@ -296,10 +306,10 @@ module Sinatra
|
|
296
306
|
attr_accessor :env, :request, :response, :params
|
297
307
|
|
298
308
|
def call!(env)
|
299
|
-
@env
|
300
|
-
@request
|
309
|
+
@env = env
|
310
|
+
@request = Request.new(env)
|
301
311
|
@response = Response.new
|
302
|
-
@params
|
312
|
+
@params = nil
|
303
313
|
error_detection { dispatch! }
|
304
314
|
@response.finish
|
305
315
|
end
|
@@ -318,13 +328,16 @@ module Sinatra
|
|
318
328
|
|
319
329
|
private
|
320
330
|
def dispatch!
|
321
|
-
self.class.filters.each
|
331
|
+
self.class.filters.each do |block|
|
332
|
+
res = catch(:halt) { instance_eval(&block) ; :continue }
|
333
|
+
return unless res == :continue
|
334
|
+
end
|
335
|
+
|
322
336
|
if routes = self.class.routes[@request.request_method]
|
323
337
|
path = @request.path_info
|
324
|
-
original_params =
|
325
|
-
original_params.merge! @request.params
|
338
|
+
original_params = nested_params(@request.params)
|
326
339
|
|
327
|
-
routes.each do |pattern, keys, conditions,
|
340
|
+
routes.each do |pattern, keys, conditions, method_name|
|
328
341
|
if pattern =~ path
|
329
342
|
values = $~.captures.map{|val| val && unescape(val) }
|
330
343
|
params =
|
@@ -342,13 +355,12 @@ module Sinatra
|
|
342
355
|
else
|
343
356
|
{}
|
344
357
|
end
|
345
|
-
@params = original_params.
|
346
|
-
@params.merge!(params)
|
358
|
+
@params = original_params.merge(params)
|
347
359
|
|
348
360
|
catch(:pass) {
|
349
361
|
conditions.each { |cond|
|
350
362
|
throw :pass if instance_eval(&cond) == false }
|
351
|
-
return invoke(
|
363
|
+
return invoke(method_name)
|
352
364
|
}
|
353
365
|
end
|
354
366
|
end
|
@@ -356,8 +368,26 @@ module Sinatra
|
|
356
368
|
raise NotFound
|
357
369
|
end
|
358
370
|
|
371
|
+
def nested_params(params)
|
372
|
+
return indifferent_hash.merge(params) if !params.keys.join.include?('[')
|
373
|
+
params.inject indifferent_hash do |res, (key,val)|
|
374
|
+
if key =~ /\[.*\]/
|
375
|
+
splat = key.scan(/(^[^\[]+)|\[([^\]]+)\]/).flatten.compact
|
376
|
+
head, last = splat[0..-2], splat[-1]
|
377
|
+
head.inject(res){ |s,v| s[v] ||= indifferent_hash }[last] = val
|
378
|
+
end
|
379
|
+
res
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def indifferent_hash
|
384
|
+
Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
385
|
+
end
|
386
|
+
|
359
387
|
def invoke(block)
|
360
388
|
res = catch(:halt) { instance_eval(&block) }
|
389
|
+
return if res.nil?
|
390
|
+
|
361
391
|
case
|
362
392
|
when res.respond_to?(:to_str)
|
363
393
|
@response.body = [res]
|
@@ -377,17 +407,12 @@ module Sinatra
|
|
377
407
|
else
|
378
408
|
@response.body = res
|
379
409
|
end
|
380
|
-
when res.kind_of?(Symbol) # TODO: deprecate this.
|
381
|
-
@response.body = __send__(res)
|
382
410
|
when res.respond_to?(:each)
|
383
411
|
@response.body = res
|
384
412
|
when (100...599) === res
|
385
413
|
@response.status = res
|
386
|
-
when res.nil?
|
387
|
-
@response.body = []
|
388
|
-
else
|
389
|
-
raise TypeError, "#{res.inspect} not supported"
|
390
414
|
end
|
415
|
+
|
391
416
|
res
|
392
417
|
end
|
393
418
|
|
@@ -402,6 +427,12 @@ module Sinatra
|
|
402
427
|
invoke handler unless handler.nil?
|
403
428
|
rescue ::Exception => boom
|
404
429
|
@env['sinatra.error'] = boom
|
430
|
+
|
431
|
+
if options.dump_errors?
|
432
|
+
msg = ["#{boom.class} - #{boom.message}:", *boom.backtrace].join("\n ")
|
433
|
+
@env['rack.errors'] << msg
|
434
|
+
end
|
435
|
+
|
405
436
|
raise boom if options.raise_errors?
|
406
437
|
@response.status = 500
|
407
438
|
invoke errmap[boom.class] || errmap[Exception]
|
@@ -454,6 +485,10 @@ module Sinatra
|
|
454
485
|
end
|
455
486
|
end
|
456
487
|
|
488
|
+
def not_found(&block)
|
489
|
+
error 404, &block
|
490
|
+
end
|
491
|
+
|
457
492
|
def template(name, &block)
|
458
493
|
templates[name] = block
|
459
494
|
end
|
@@ -463,11 +498,16 @@ module Sinatra
|
|
463
498
|
end
|
464
499
|
|
465
500
|
def use_in_file_templates!
|
466
|
-
line = caller.detect
|
467
|
-
|
501
|
+
line = caller.detect do |s|
|
502
|
+
[
|
503
|
+
/lib\/sinatra.*\.rb/,
|
504
|
+
/\(.*\)/,
|
505
|
+
/rubygems\/custom_require\.rb/
|
506
|
+
].all? { |x| s !~ x }
|
507
|
+
end
|
468
508
|
file = line.sub(/:\d+.*$/, '')
|
469
509
|
if data = ::IO.read(file).split('__END__')[1]
|
470
|
-
data.gsub!
|
510
|
+
data.gsub!(/\r\n/, "\n")
|
471
511
|
template = nil
|
472
512
|
data.each_line do |line|
|
473
513
|
if line =~ /^@@\s*(.*)/
|
@@ -479,6 +519,13 @@ module Sinatra
|
|
479
519
|
end
|
480
520
|
end
|
481
521
|
|
522
|
+
# Look up a media type by file extension in Rack's mime registry.
|
523
|
+
def media_type(type)
|
524
|
+
return type if type.nil? || type.to_s.include?('/')
|
525
|
+
type = ".#{type}" unless type.to_s[0] == ?.
|
526
|
+
Rack::Mime.mime_type(type, nil)
|
527
|
+
end
|
528
|
+
|
482
529
|
def before(&block)
|
483
530
|
@filters << block
|
484
531
|
end
|
@@ -502,9 +549,24 @@ module Sinatra
|
|
502
549
|
}
|
503
550
|
end
|
504
551
|
|
552
|
+
def accept_mime_types(types)
|
553
|
+
types = [types] unless types.kind_of? Array
|
554
|
+
types.map!{|t| media_type(t)}
|
555
|
+
|
556
|
+
condition {
|
557
|
+
matching_types = (request.accept & types)
|
558
|
+
unless matching_types.empty?
|
559
|
+
response.headers['Content-Type'] = matching_types.first
|
560
|
+
true
|
561
|
+
else
|
562
|
+
false
|
563
|
+
end
|
564
|
+
}
|
565
|
+
end
|
566
|
+
|
505
567
|
def get(path, opts={}, &block)
|
506
568
|
conditions = @conditions.dup
|
507
|
-
route
|
569
|
+
route('GET', path, opts, &block)
|
508
570
|
|
509
571
|
@conditions = conditions
|
510
572
|
head(path, opts) { invoke(block) ; [] }
|
@@ -516,14 +578,20 @@ module Sinatra
|
|
516
578
|
def head(path, opts={}, &bk); route 'HEAD', path, opts, &bk; end
|
517
579
|
|
518
580
|
private
|
519
|
-
def route(
|
581
|
+
def route(verb, path, opts={}, &block)
|
520
582
|
host_name opts[:host] if opts.key?(:host)
|
521
583
|
user_agent opts[:agent] if opts.key?(:agent)
|
584
|
+
accept_mime_types opts[:provides] if opts.key?(:provides)
|
522
585
|
|
523
586
|
pattern, keys = compile(path)
|
524
587
|
conditions, @conditions = @conditions, []
|
525
|
-
|
526
|
-
|
588
|
+
|
589
|
+
define_method "#{verb} #{path}", &block
|
590
|
+
unbound_method = instance_method("#{verb} #{path}")
|
591
|
+
block = lambda { unbound_method.bind(self).call }
|
592
|
+
|
593
|
+
(routes[verb] ||= []).
|
594
|
+
push([pattern, keys, conditions, block]).last
|
527
595
|
end
|
528
596
|
|
529
597
|
def compile(path)
|
@@ -562,8 +630,8 @@ module Sinatra
|
|
562
630
|
end
|
563
631
|
|
564
632
|
def run!(options={})
|
565
|
-
set
|
566
|
-
handler =
|
633
|
+
set options
|
634
|
+
handler = detect_rack_handler
|
567
635
|
handler_name = handler.name.gsub(/.*::/, '')
|
568
636
|
puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
|
569
637
|
"on #{port} for #{environment} with backup from #{handler_name}"
|
@@ -584,6 +652,17 @@ module Sinatra
|
|
584
652
|
end
|
585
653
|
|
586
654
|
private
|
655
|
+
def detect_rack_handler
|
656
|
+
servers = Array(self.server)
|
657
|
+
servers.each do |server_name|
|
658
|
+
begin
|
659
|
+
return Rack::Handler.get(server_name)
|
660
|
+
rescue LoadError
|
661
|
+
end
|
662
|
+
end
|
663
|
+
fail "Server handler (#{servers.join(',')}) not found."
|
664
|
+
end
|
665
|
+
|
587
666
|
def construct_middleware(builder=Rack::Builder.new)
|
588
667
|
builder.use Rack::Session::Cookie if sessions?
|
589
668
|
builder.use Rack::CommonLogger if logging?
|
@@ -622,6 +701,7 @@ module Sinatra
|
|
622
701
|
end
|
623
702
|
|
624
703
|
set :raise_errors, true
|
704
|
+
set :dump_errors, false
|
625
705
|
set :sessions, false
|
626
706
|
set :logging, false
|
627
707
|
set :methodoverride, false
|
@@ -629,7 +709,7 @@ module Sinatra
|
|
629
709
|
set :environment, (ENV['RACK_ENV'] || :development).to_sym
|
630
710
|
|
631
711
|
set :run, false
|
632
|
-
set :server,
|
712
|
+
set :server, %w[thin mongrel webrick]
|
633
713
|
set :host, '0.0.0.0'
|
634
714
|
set :port, 4567
|
635
715
|
|
@@ -715,34 +795,45 @@ module Sinatra
|
|
715
795
|
|
716
796
|
class Default < Base
|
717
797
|
set :raise_errors, false
|
798
|
+
set :dump_errors, true
|
718
799
|
set :sessions, false
|
719
800
|
set :logging, true
|
720
801
|
set :methodoverride, true
|
721
802
|
set :static, true
|
722
803
|
set :run, false
|
723
804
|
set :reload, Proc.new { app_file? && development? }
|
805
|
+
set :lock, Proc.new { reload? }
|
724
806
|
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
def reloading?
|
729
|
-
@reloading
|
730
|
-
end
|
807
|
+
def self.reloading?
|
808
|
+
@reloading ||= false
|
809
|
+
end
|
731
810
|
|
732
|
-
|
733
|
-
|
734
|
-
|
811
|
+
def self.configure(*envs)
|
812
|
+
super unless reloading?
|
813
|
+
end
|
735
814
|
|
736
|
-
|
815
|
+
def self.call(env)
|
816
|
+
synchronize do
|
737
817
|
reload! if reload?
|
738
818
|
super
|
739
819
|
end
|
820
|
+
end
|
821
|
+
|
822
|
+
def self.reload!
|
823
|
+
@reloading = true
|
824
|
+
superclass.send :inherited, self
|
825
|
+
$LOADED_FEATURES.delete("sinatra.rb")
|
826
|
+
::Kernel.load app_file
|
827
|
+
@reloading = false
|
828
|
+
end
|
740
829
|
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
830
|
+
private
|
831
|
+
@@mutex = Mutex.new
|
832
|
+
def self.synchronize(&block)
|
833
|
+
if lock?
|
834
|
+
@@mutex.synchronize(&block)
|
835
|
+
else
|
836
|
+
yield
|
746
837
|
end
|
747
838
|
end
|
748
839
|
end
|