bmizerany-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 +204 -110
- 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/AUTHORS
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Sinatra was designed and developed by Blake Mizerany (bmizerany) in
|
2
2
|
California. Continued development would not be possible without the ongoing
|
3
3
|
financial support provided by [Heroku](http://heroku.com) and the emotional
|
4
|
-
support provided by Adam Wiggins (adamwiggins), Chris Wanstrath (defunkt),
|
4
|
+
support provided by Adam Wiggins (adamwiggins) of Heroku, Chris Wanstrath (defunkt),
|
5
5
|
PJ Hyett (pjhyett), and the rest of the GitHub crew.
|
6
6
|
|
7
7
|
Special thanks to the following extraordinary individuals, who-out which
|
data/CHANGES
CHANGED
@@ -1,3 +1,47 @@
|
|
1
|
+
= 0.9.1 / unreleased
|
2
|
+
|
3
|
+
* Sinatra now runs under Ruby 1.9.1 [#61]
|
4
|
+
* Route patterns (splats, :named, or Regexp captures) are now
|
5
|
+
passed as arguments to the block. [#140]
|
6
|
+
* The "helpers" method now takes a variable number of modules
|
7
|
+
along with the normal block syntax. [#133]
|
8
|
+
* New simple API for extensions/plugins to add DSL-level and
|
9
|
+
request-level methods. Use Sinatra.register(mixin) to extend
|
10
|
+
the DSL with all public methods defined in the mixin module;
|
11
|
+
use Sinatra.helpers(mixin) to make all public methods defined
|
12
|
+
in the mixin module available at the request level. [#138]
|
13
|
+
* Added "redirect back" to redirect to the referring URL.
|
14
|
+
* Added a new "clean_trace" option that causes backtraces dumped
|
15
|
+
to rack.errors and displayed on the development error page to
|
16
|
+
omit framework and core library backtrace lines. The option is
|
17
|
+
enabled by default. [#77]
|
18
|
+
* Fix :provides causing crash on any request when request has no
|
19
|
+
Accept header [#139]
|
20
|
+
* Fix that ERB templates were evaluated twice per "erb" call.
|
21
|
+
|
22
|
+
= 0.9.0.4 / 2009-01-25
|
23
|
+
|
24
|
+
* Using halt with more than 1 args causes ArgumentError [#131]
|
25
|
+
* using halt in a before filter doesn't modify response [#127]
|
26
|
+
* Add deprecated Sinatra::EventContext to unbreak plugins [#130]
|
27
|
+
* Give access to GET/POST params in filters [#129]
|
28
|
+
* Preserve non-nested params in nested params hash [#117]
|
29
|
+
* Fix backtrace dump with Rack::Lint [#116]
|
30
|
+
|
31
|
+
= 0.9.0.3 / 2009-01-21
|
32
|
+
|
33
|
+
* Fall back on mongrel then webrick when thin not found. [#75]
|
34
|
+
* Use :environment instead of :env in test helpers to
|
35
|
+
fix deprecation warnings coming from framework.
|
36
|
+
* Make sinatra/test/rspec work again [#113]
|
37
|
+
* Fix app_file detection on windows [#118]
|
38
|
+
* Fix static files with Rack::Lint in pipeline [#121]
|
39
|
+
|
40
|
+
= 0.9.0.2 / 2009-01-18
|
41
|
+
|
42
|
+
* Halting a before block should stop processing of routes [#85]
|
43
|
+
* Fix redirect/halt in before filters [#85]
|
44
|
+
|
1
45
|
= 0.9.0 / 2009-01-18
|
2
46
|
|
3
47
|
* Works with and requires Rack >= 0.9.1
|
data/README.rdoc
CHANGED
@@ -50,6 +50,12 @@ Route patterns may include named parameters, accessible via the
|
|
50
50
|
"Hello #{params[:name]}!"
|
51
51
|
end
|
52
52
|
|
53
|
+
You can also access named parameters via block parameters:
|
54
|
+
|
55
|
+
get '/hello/:name' do |n|
|
56
|
+
"Hello #{n}!"
|
57
|
+
end
|
58
|
+
|
53
59
|
Route patterns may also include splat (or wildcard) parameters, accessible
|
54
60
|
via the <tt>params[:splat]</tt> array.
|
55
61
|
|
@@ -69,6 +75,12 @@ Route matching with Regular Expressions:
|
|
69
75
|
"Hello, #{params[:captures].first}!"
|
70
76
|
end
|
71
77
|
|
78
|
+
Or with a block parameter:
|
79
|
+
|
80
|
+
get %r{/hello/([\w]+)} do |c|
|
81
|
+
"Hello, #{c}!"
|
82
|
+
end
|
83
|
+
|
72
84
|
Routes may include a variety of matching conditions, such as the user agent:
|
73
85
|
|
74
86
|
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rake/clean'
|
|
2
2
|
require 'rake/testtask'
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
|
-
task :default => :test
|
5
|
+
task :default => [:test]
|
6
6
|
task :spec => :test
|
7
7
|
|
8
8
|
# SPECS ===============================================================
|
@@ -45,6 +45,7 @@ task :install => package('.gem') do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
directory 'dist/'
|
48
|
+
CLOBBER.include('dist')
|
48
49
|
|
49
50
|
file package('.gem') => %w[dist/ sinatra.gemspec] + spec.files do |f|
|
50
51
|
sh "gem build sinatra.gemspec"
|
data/compat/app_test.rb
CHANGED
@@ -8,8 +8,9 @@ context "Sinatra" do
|
|
8
8
|
|
9
9
|
specify "should put all DSL methods on (main)" do
|
10
10
|
object = Object.new
|
11
|
-
|
12
|
-
|
11
|
+
methods = %w[get put post head delete configure template helpers set]
|
12
|
+
methods.each do |method|
|
13
|
+
object.private_methods.map { |m| m.to_sym }.should.include(method.to_sym)
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
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|
|
@@ -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
926
|
|
852
|
-
def self.
|
853
|
-
|
854
|
-
|
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
|
-
|
875
|
-
private
|
876
|
-
@@mutex = Mutex.new
|
877
|
-
def self.synchronize(&block)
|
878
|
-
if lock?
|
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,47 @@ 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) do
|
1000
|
+
expanded = File.expand_path(file)
|
1001
|
+
self.class_eval { set :app_file, expanded }
|
1002
|
+
self.class_eval(File.read(expanded), expanded)
|
1003
|
+
end
|
1004
|
+
end
|
911
1005
|
end
|