sinatra 0.9.6 → 1.0.a
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- data/CHANGES +83 -29
- data/README.jp.rdoc +552 -0
- data/README.rdoc +31 -9
- data/Rakefile +73 -91
- data/lib/sinatra.rb +0 -1
- data/lib/sinatra/base.rb +248 -269
- data/lib/sinatra/main.rb +3 -11
- data/lib/sinatra/tilt.rb +509 -0
- data/sinatra.gemspec +15 -49
- data/test/erubis_test.rb +82 -0
- data/test/extensions_test.rb +1 -1
- data/test/filter_test.rb +125 -3
- data/test/helpers_test.rb +59 -2
- data/test/mapped_error_test.rb +31 -0
- data/test/middleware_test.rb +1 -1
- data/test/request_test.rb +15 -0
- data/test/routing_test.rb +76 -0
- data/test/{options_test.rb → settings_test.rb} +46 -50
- data/test/static_test.rb +13 -0
- data/test/templates_test.rb +43 -10
- data/test/views/error.erubis +3 -0
- data/test/views/hello.erubis +1 -0
- data/test/views/layout2.erubis +2 -0
- metadata +61 -88
- data/compat/app_test.rb +0 -282
- data/compat/application_test.rb +0 -262
- data/compat/builder_test.rb +0 -101
- data/compat/compat_test.rb +0 -12
- data/compat/custom_error_test.rb +0 -62
- data/compat/erb_test.rb +0 -136
- data/compat/events_test.rb +0 -78
- data/compat/filter_test.rb +0 -30
- data/compat/haml_test.rb +0 -237
- data/compat/helper.rb +0 -34
- data/compat/mapped_error_test.rb +0 -72
- data/compat/pipeline_test.rb +0 -45
- data/compat/public/foo.xml +0 -1
- data/compat/sass_test.rb +0 -67
- data/compat/sessions_test.rb +0 -42
- data/compat/streaming_test.rb +0 -133
- data/compat/sym_params_test.rb +0 -18
- data/compat/template_test.rb +0 -30
- data/compat/use_in_file_templates_test.rb +0 -47
- data/compat/views/foo.builder +0 -1
- data/compat/views/foo.erb +0 -1
- data/compat/views/foo.haml +0 -1
- data/compat/views/foo.sass +0 -2
- data/compat/views/foo_layout.erb +0 -2
- data/compat/views/foo_layout.haml +0 -2
- data/compat/views/layout_test/foo.builder +0 -1
- data/compat/views/layout_test/foo.erb +0 -1
- data/compat/views/layout_test/foo.haml +0 -1
- data/compat/views/layout_test/foo.sass +0 -2
- data/compat/views/layout_test/layout.builder +0 -3
- data/compat/views/layout_test/layout.erb +0 -1
- data/compat/views/layout_test/layout.haml +0 -1
- data/compat/views/layout_test/layout.sass +0 -2
- data/compat/views/no_layout/no_layout.builder +0 -1
- data/compat/views/no_layout/no_layout.haml +0 -1
- data/lib/sinatra/compat.rb +0 -258
- data/lib/sinatra/test.rb +0 -129
- data/lib/sinatra/test/bacon.rb +0 -19
- data/lib/sinatra/test/rspec.rb +0 -13
- data/lib/sinatra/test/spec.rb +0 -11
- data/lib/sinatra/test/unit.rb +0 -13
- data/test/render_backtrace_test.rb +0 -145
- data/test/test_test.rb +0 -155
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Sinatra
|
2
2
|
|
3
|
-
Sinatra is a DSL for quickly creating web
|
3
|
+
Sinatra is a DSL for quickly creating web applications in Ruby with minimal
|
4
4
|
effort:
|
5
5
|
|
6
6
|
# myapp.rb
|
@@ -150,6 +150,19 @@ and overridden on an individual basis.
|
|
150
150
|
|
151
151
|
Renders <tt>./views/index.erb</tt>
|
152
152
|
|
153
|
+
=== Erubis
|
154
|
+
|
155
|
+
The erubis gem/library is required to render builder templates:
|
156
|
+
|
157
|
+
## You'll need to require erubis in your app
|
158
|
+
require 'erubis'
|
159
|
+
|
160
|
+
get '/' do
|
161
|
+
erubis :index
|
162
|
+
end
|
163
|
+
|
164
|
+
Renders <tt>./views/index.erubis</tt>
|
165
|
+
|
153
166
|
=== Builder Templates
|
154
167
|
|
155
168
|
The builder gem/library is required to render builder templates:
|
@@ -296,9 +309,17 @@ filters are accessible by routes and templates:
|
|
296
309
|
params[:splat] #=> 'bar/baz'
|
297
310
|
end
|
298
311
|
|
312
|
+
After filter are evaluated after each request within the context of the
|
313
|
+
request and can also modify the request and response. Instance variables
|
314
|
+
set in before filters and routes are accessible by after filters:
|
315
|
+
|
316
|
+
after do
|
317
|
+
puts response.status
|
318
|
+
end
|
319
|
+
|
299
320
|
== Halting
|
300
321
|
|
301
|
-
To immediately stop a request
|
322
|
+
To immediately stop a request within a filter or route use:
|
302
323
|
|
303
324
|
halt
|
304
325
|
|
@@ -374,7 +395,7 @@ code is 404, the <tt>not_found</tt> handler is invoked:
|
|
374
395
|
=== Error
|
375
396
|
|
376
397
|
The +error+ handler is invoked any time an exception is raised from a route
|
377
|
-
block or
|
398
|
+
block or a filter. The exception object can be obtained from the
|
378
399
|
<tt>sinatra.error</tt> Rack variable:
|
379
400
|
|
380
401
|
error do
|
@@ -544,19 +565,20 @@ system. The +Sinatra::Application+ class -- a special subclass of
|
|
544
565
|
Sinatra::Base -- receives all :get, :put, :post, :delete, :before,
|
545
566
|
:error, :not_found, :configure, and :set messages sent to the
|
546
567
|
top-level. Have a look at the code for yourself: here's the
|
547
|
-
{Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/
|
548
|
-
being {included into the main namespace}[http://github.com/sinatra/sinatra/blob/
|
568
|
+
{Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1064]
|
569
|
+
being {included into the main namespace}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb#L25].
|
549
570
|
|
550
571
|
== Command line
|
551
572
|
|
552
573
|
Sinatra applications can be run directly:
|
553
574
|
|
554
|
-
ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-s HANDLER]
|
575
|
+
ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-h HOST] [-s HANDLER]
|
555
576
|
|
556
577
|
Options are:
|
557
578
|
|
558
579
|
-h # help
|
559
580
|
-p # set the port (default is 4567)
|
581
|
+
-h # set the host (default is 0.0.0.0)
|
560
582
|
-e # set the environment (default is development)
|
561
583
|
-s # specify rack server/handler (default is thin)
|
562
584
|
-x # turn on the mutex lock (default is off)
|
@@ -589,12 +611,12 @@ To update the Sinatra sources in the future:
|
|
589
611
|
|
590
612
|
== More
|
591
613
|
|
592
|
-
* {Project Website}[http://
|
614
|
+
* {Project Website}[http://sinatra.github.com/] - Additional documentation,
|
593
615
|
news, and links to other resources.
|
594
|
-
* {Contributing}[http://
|
616
|
+
* {Contributing}[http://sinatra.github.com/contributing.html] - Find a bug? Need
|
595
617
|
help? Have a patch?
|
596
618
|
* {Lighthouse}[http://sinatra.lighthouseapp.com] - Issue tracking and release
|
597
619
|
planning.
|
598
620
|
* {Twitter}[http://twitter.com/sinatra]
|
599
|
-
* {Mailing List}[http://groups.google.com/group/sinatrarb
|
621
|
+
* {Mailing List}[http://groups.google.com/group/sinatrarb]
|
600
622
|
* {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net
|
data/Rakefile
CHANGED
@@ -2,88 +2,38 @@ require 'rake/clean'
|
|
2
2
|
require 'rake/testtask'
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
|
-
task :default =>
|
5
|
+
task :default => :test
|
6
6
|
task :spec => :test
|
7
7
|
|
8
|
-
|
8
|
+
def source_version
|
9
|
+
line = File.read('lib/sinatra/base.rb')[/^\s*VERSION = .*/]
|
10
|
+
line.match(/.*VERSION = '(.*)'/)[1]
|
11
|
+
end
|
9
12
|
|
10
|
-
|
13
|
+
# SPECS ===============================================================
|
11
14
|
|
12
15
|
Rake::TestTask.new(:test) do |t|
|
13
16
|
t.test_files = FileList['test/*_test.rb']
|
14
|
-
t.ruby_opts = ['-rubygems'] if defined? Gem
|
17
|
+
t.ruby_opts = ['-rubygems -I.'] if defined? Gem
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
puts "==> Running compat test suite"
|
25
|
-
Rake::TestTask.new(:compat) do |t|
|
26
|
-
t.test_files = FileList['compat/*_test.rb']
|
27
|
-
t.ruby_opts = ['-rubygems'] if defined? Gem
|
28
|
-
end
|
29
|
-
rescue LoadError
|
30
|
-
warn 'Skipping compat tests. mocha and/or test-spec gems not installed.'
|
20
|
+
# Rcov ================================================================
|
21
|
+
namespace :test do
|
22
|
+
desc 'Mesures test coverage'
|
23
|
+
task :coverage do
|
24
|
+
rm_f "coverage"
|
25
|
+
rcov = "rcov --text-summary --test-unit-only -Ilib"
|
26
|
+
system("#{rcov} --no-html --no-color test/*_test.rb")
|
31
27
|
end
|
32
28
|
end
|
33
29
|
|
34
|
-
#
|
35
|
-
|
36
|
-
# Load the gemspec using the same limitations as github
|
37
|
-
def spec
|
38
|
-
@spec ||= eval(File.read('sinatra.gemspec'))
|
39
|
-
end
|
40
|
-
|
41
|
-
def package(ext='')
|
42
|
-
"pkg/sinatra-#{spec.version}" + ext
|
43
|
-
end
|
44
|
-
|
45
|
-
desc 'Build packages'
|
46
|
-
task :package => %w[.gem .tar.gz].map {|e| package(e)}
|
47
|
-
|
48
|
-
desc 'Build and install as local gem'
|
49
|
-
task :install => package('.gem') do
|
50
|
-
sh "gem install #{package('.gem')}"
|
51
|
-
end
|
52
|
-
|
53
|
-
directory 'pkg/'
|
54
|
-
CLOBBER.include('pkg')
|
55
|
-
|
56
|
-
file package('.gem') => %w[pkg/ sinatra.gemspec] + spec.files do |f|
|
57
|
-
sh "gem build sinatra.gemspec"
|
58
|
-
mv File.basename(f.name), f.name
|
59
|
-
end
|
60
|
-
|
61
|
-
file package('.tar.gz') => %w[pkg/] + spec.files do |f|
|
62
|
-
sh <<-SH
|
63
|
-
git archive \
|
64
|
-
--prefix=sinatra-#{source_version}/ \
|
65
|
-
--format=tar \
|
66
|
-
HEAD | gzip > #{f.name}
|
67
|
-
SH
|
68
|
-
end
|
69
|
-
|
70
|
-
# Rubyforge Release / Publish Tasks ==================================
|
71
|
-
|
72
|
-
desc 'Publish gem and tarball to rubyforge'
|
73
|
-
task 'release' => [package('.gem'), package('.tar.gz')] do |t|
|
74
|
-
sh <<-end
|
75
|
-
rubyforge add_release sinatra sinatra #{spec.version} #{package('.gem')} &&
|
76
|
-
rubyforge add_file sinatra sinatra #{spec.version} #{package('.tar.gz')}
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# Website ============================================================
|
30
|
+
# Website =============================================================
|
81
31
|
# Building docs requires HAML and the hanna gem:
|
82
32
|
# gem install mislav-hanna --source=http://gems.github.com
|
83
33
|
|
34
|
+
desc 'Generate RDoc under doc/api'
|
84
35
|
task 'doc' => ['doc:api']
|
85
36
|
|
86
|
-
desc 'Generate Hanna RDoc under doc/api'
|
87
37
|
task 'doc:api' => ['doc/api/index.html']
|
88
38
|
|
89
39
|
file 'doc/api/index.html' => FileList['lib/**/*.rb','README.rdoc'] do |f|
|
@@ -101,31 +51,63 @@ file 'doc/api/index.html' => FileList['lib/**/*.rb','README.rdoc'] do |f|
|
|
101
51
|
end
|
102
52
|
CLEAN.include 'doc/api'
|
103
53
|
|
104
|
-
#
|
54
|
+
# PACKAGING ============================================================
|
105
55
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
56
|
+
if defined?(Gem)
|
57
|
+
# Load the gemspec using the same limitations as github
|
58
|
+
def spec
|
59
|
+
require 'rubygems' unless defined? Gem::Specification
|
60
|
+
@spec ||= eval(File.read('sinatra.gemspec'))
|
61
|
+
end
|
62
|
+
|
63
|
+
def package(ext='')
|
64
|
+
"pkg/sinatra-#{spec.version}" + ext
|
65
|
+
end
|
66
|
+
|
67
|
+
desc 'Build packages'
|
68
|
+
task :package => %w[.gem .tar.gz].map {|e| package(e)}
|
69
|
+
|
70
|
+
desc 'Build and install as local gem'
|
71
|
+
task :install => package('.gem') do
|
72
|
+
sh "gem install #{package('.gem')}"
|
73
|
+
end
|
74
|
+
|
75
|
+
directory 'pkg/'
|
76
|
+
CLOBBER.include('pkg')
|
110
77
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
78
|
+
file package('.gem') => %w[pkg/ sinatra.gemspec] + spec.files do |f|
|
79
|
+
sh "gem build sinatra.gemspec"
|
80
|
+
mv File.basename(f.name), f.name
|
81
|
+
end
|
82
|
+
|
83
|
+
file package('.tar.gz') => %w[pkg/] + spec.files do |f|
|
84
|
+
sh <<-SH
|
85
|
+
git archive \
|
86
|
+
--prefix=sinatra-#{source_version}/ \
|
87
|
+
--format=tar \
|
88
|
+
HEAD | gzip > #{f.name}
|
89
|
+
SH
|
90
|
+
end
|
91
|
+
|
92
|
+
task 'sinatra.gemspec' => FileList['{lib,test,compat}/**','Rakefile','CHANGES','*.rdoc'] do |f|
|
93
|
+
# read spec file and split out manifest section
|
94
|
+
spec = File.read(f.name)
|
95
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
96
|
+
# replace version and date
|
97
|
+
head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
|
98
|
+
head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
|
99
|
+
# determine file list from git ls-files
|
100
|
+
files = `git ls-files`.
|
101
|
+
split("\n").
|
102
|
+
sort.
|
103
|
+
reject{ |file| file =~ /^\./ }.
|
104
|
+
reject { |file| file =~ /^doc/ }.
|
105
|
+
map{ |file| " #{file}" }.
|
106
|
+
join("\n")
|
107
|
+
# piece file back together and write...
|
108
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
109
|
+
spec = [head,manifest,tail].join(" # = MANIFEST =\n")
|
110
|
+
File.open(f.name, 'w') { |io| io.write(spec) }
|
111
|
+
puts "updated #{f.name}"
|
112
|
+
end
|
131
113
|
end
|
data/lib/sinatra.rb
CHANGED
data/lib/sinatra/base.rb
CHANGED
@@ -5,34 +5,41 @@ require 'rack'
|
|
5
5
|
require 'rack/builder'
|
6
6
|
require 'sinatra/showexceptions'
|
7
7
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
warn "#{line}: warning: #{message.join(' ')}"
|
8
|
+
# require tilt if available; fall back on bundled version.
|
9
|
+
begin
|
10
|
+
require 'tilt'
|
11
|
+
rescue LoadError
|
12
|
+
require 'sinatra/tilt'
|
14
13
|
end
|
15
14
|
|
16
15
|
module Sinatra
|
17
|
-
VERSION = '0.
|
16
|
+
VERSION = '1.0.a'
|
18
17
|
|
19
18
|
# The request object. See Rack::Request for more info:
|
20
19
|
# http://rack.rubyforge.org/doc/classes/Rack/Request.html
|
21
20
|
class Request < Rack::Request
|
22
|
-
def user_agent
|
23
|
-
@env['HTTP_USER_AGENT']
|
24
|
-
end
|
25
|
-
|
26
21
|
# Returns an array of acceptable media types for the response
|
27
22
|
def accept
|
28
23
|
@env['HTTP_ACCEPT'].to_s.split(',').map { |a| a.strip }
|
29
24
|
end
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
26
|
+
def secure?
|
27
|
+
(@env['HTTP_X_FORWARDED_PROTO'] || @env['rack.url_scheme']) == 'https'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Override Rack < 1.1's Request#params implementation (see lh #72 for
|
31
|
+
# more info) and add a Request#user_agent method.
|
32
|
+
# XXX remove when we require rack > 1.1
|
33
|
+
if Rack.release < '1.1'
|
34
|
+
def params
|
35
|
+
self.GET.update(self.POST)
|
36
|
+
rescue EOFError, Errno::ESPIPE
|
37
|
+
self.GET
|
38
|
+
end
|
39
|
+
|
40
|
+
def user_agent
|
41
|
+
@env['HTTP_USER_AGENT']
|
42
|
+
end
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
@@ -51,7 +58,7 @@ module Sinatra
|
|
51
58
|
body = [body] if body.respond_to? :to_str
|
52
59
|
if body.respond_to?(:to_ary)
|
53
60
|
header["Content-Length"] = body.to_ary.
|
54
|
-
inject(0) { |len, part| len +
|
61
|
+
inject(0) { |len, part| len + Rack::Utils.bytesize(part) }.to_s
|
55
62
|
end
|
56
63
|
[status.to_i, header.to_hash, body]
|
57
64
|
end
|
@@ -62,7 +69,7 @@ module Sinatra
|
|
62
69
|
def code ; 404 ; end
|
63
70
|
end
|
64
71
|
|
65
|
-
# Methods available to routes, before filters, and views.
|
72
|
+
# Methods available to routes, before/after filters, and views.
|
66
73
|
module Helpers
|
67
74
|
# Set or retrieve the response status code.
|
68
75
|
def status(value=nil)
|
@@ -116,11 +123,6 @@ module Sinatra
|
|
116
123
|
Base.mime_type(type)
|
117
124
|
end
|
118
125
|
|
119
|
-
def media_type(type)
|
120
|
-
sinatra_warn "media_type is deprecated; use mime_type instead"
|
121
|
-
mime_type(type)
|
122
|
-
end
|
123
|
-
|
124
126
|
# Set the Content-Type of the response body given a media type or file
|
125
127
|
# extension.
|
126
128
|
def content_type(type, params={})
|
@@ -179,6 +181,57 @@ module Sinatra
|
|
179
181
|
end
|
180
182
|
end
|
181
183
|
|
184
|
+
# Specify response freshness policy for HTTP caches (Cache-Control header).
|
185
|
+
# Any number of non-value directives (:public, :private, :no_cache,
|
186
|
+
# :no_store, :must_revalidate, :proxy_revalidate) may be passed along with
|
187
|
+
# a Hash of value directives (:max_age, :min_stale, :s_max_age).
|
188
|
+
#
|
189
|
+
# cache_control :public, :must_revalidate, :max_age => 60
|
190
|
+
# => Cache-Control: public, must-revalidate, max-age=60
|
191
|
+
#
|
192
|
+
# See RFC 2616 / 14.9 for more on standard cache control directives:
|
193
|
+
# http://tools.ietf.org/html/rfc2616#section-14.9.1
|
194
|
+
def cache_control(*values)
|
195
|
+
if values.last.kind_of?(Hash)
|
196
|
+
hash = values.pop
|
197
|
+
hash.reject! { |k,v| v == false }
|
198
|
+
hash.reject! { |k,v| values << k if v == true }
|
199
|
+
else
|
200
|
+
hash = {}
|
201
|
+
end
|
202
|
+
|
203
|
+
values = values.map { |value| value.to_s.tr('_','-') }
|
204
|
+
hash.each { |k,v| values << [k.to_s.tr('_', '-'), v].join('=') }
|
205
|
+
|
206
|
+
response['Cache-Control'] = values.join(', ') if values.any?
|
207
|
+
end
|
208
|
+
|
209
|
+
# Set the Expires header and Cache-Control/max-age directive. Amount
|
210
|
+
# can be an integer number of seconds in the future or a Time object
|
211
|
+
# indicating when the response should be considered "stale". The remaining
|
212
|
+
# "values" arguments are passed to the #cache_control helper:
|
213
|
+
#
|
214
|
+
# expires 500, :public, :must_revalidate
|
215
|
+
# => Cache-Control: public, must-revalidate, max-age=60
|
216
|
+
# => Expires: Mon, 08 Jun 2009 08:50:17 GMT
|
217
|
+
#
|
218
|
+
def expires(amount, *values)
|
219
|
+
values << {} unless values.last.kind_of?(Hash)
|
220
|
+
|
221
|
+
if amount.respond_to?(:to_time)
|
222
|
+
max_age = amount.to_time - Time.now
|
223
|
+
time = amount.to_time
|
224
|
+
else
|
225
|
+
max_age = amount
|
226
|
+
time = Time.now + amount
|
227
|
+
end
|
228
|
+
|
229
|
+
values.last.merge!(:max_age => max_age)
|
230
|
+
cache_control(*values)
|
231
|
+
|
232
|
+
response['Expires'] = time.httpdate
|
233
|
+
end
|
234
|
+
|
182
235
|
# Set the last modified time of the resource (HTTP 'Last-Modified' header)
|
183
236
|
# and halt if conditional GET matches. The +time+ argument is a Time,
|
184
237
|
# DateTime, or other object that responds to +to_time+.
|
@@ -221,7 +274,7 @@ module Sinatra
|
|
221
274
|
|
222
275
|
end
|
223
276
|
|
224
|
-
# Template rendering methods. Each method takes
|
277
|
+
# Template rendering methods. Each method takes the name of a template
|
225
278
|
# to render as a Symbol and returns a String with the rendered output,
|
226
279
|
# as well as an optional hash with additional options.
|
227
280
|
#
|
@@ -236,127 +289,76 @@ module Sinatra
|
|
236
289
|
# in the template
|
237
290
|
module Templates
|
238
291
|
def erb(template, options={}, locals={})
|
239
|
-
require_warn('ERB') unless defined?(::ERB)
|
240
|
-
|
241
292
|
render :erb, template, options, locals
|
242
293
|
end
|
243
294
|
|
244
|
-
def
|
245
|
-
|
295
|
+
def erubis(template, options={}, locals={})
|
296
|
+
render :erubis, template, options, locals
|
297
|
+
end
|
246
298
|
|
299
|
+
def haml(template, options={}, locals={})
|
247
300
|
render :haml, template, options, locals
|
248
301
|
end
|
249
302
|
|
250
303
|
def sass(template, options={}, locals={})
|
251
|
-
require_warn('Sass') unless defined?(::Sass::Engine)
|
252
|
-
|
253
304
|
options[:layout] = false
|
254
305
|
render :sass, template, options, locals
|
255
306
|
end
|
256
307
|
|
257
308
|
def builder(template=nil, options={}, locals={}, &block)
|
258
|
-
require_warn('Builder') unless defined?(::Builder)
|
259
|
-
|
260
309
|
options, template = template, nil if template.is_a?(Hash)
|
261
|
-
template =
|
310
|
+
template = Proc.new { block } if template.nil?
|
262
311
|
render :builder, template, options, locals
|
263
312
|
end
|
264
313
|
|
265
314
|
private
|
266
|
-
def render(engine,
|
315
|
+
def render(engine, data, options={}, locals={}, &block)
|
267
316
|
# merge app-level options
|
268
|
-
options =
|
317
|
+
options = settings.send(engine).merge(options) if settings.respond_to?(engine)
|
269
318
|
|
270
319
|
# extract generic options
|
320
|
+
locals = options.delete(:locals) || locals || {}
|
321
|
+
views = options.delete(:views) || settings.views || "./views"
|
271
322
|
layout = options.delete(:layout)
|
272
323
|
layout = :layout if layout.nil? || layout == true
|
273
|
-
views = options.delete(:views) || self.class.views || "./views"
|
274
|
-
locals = options.delete(:locals) || locals || {}
|
275
324
|
|
276
|
-
# render template
|
277
|
-
|
278
|
-
output =
|
325
|
+
# compile and render template
|
326
|
+
template = compile_template(engine, data, options, views)
|
327
|
+
output = template.render(self, locals, &block)
|
279
328
|
|
280
329
|
# render layout
|
281
330
|
if layout
|
282
|
-
|
283
|
-
|
284
|
-
output =
|
331
|
+
begin
|
332
|
+
options = options.merge(:views => views, :layout => false)
|
333
|
+
output = render(engine, layout, options, locals) { output }
|
334
|
+
rescue Errno::ENOENT
|
285
335
|
end
|
286
336
|
end
|
287
337
|
|
288
338
|
output
|
289
339
|
end
|
290
340
|
|
291
|
-
def
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
341
|
+
def compile_template(engine, data, options, views)
|
342
|
+
@template_cache.fetch engine, data, options do
|
343
|
+
case
|
344
|
+
when data.is_a?(Symbol)
|
345
|
+
body, path, line = self.class.templates[data]
|
346
|
+
if body
|
347
|
+
body = body.call if body.respond_to?(:call)
|
348
|
+
Tilt[engine].new(path, line.to_i, options) { body }
|
349
|
+
else
|
350
|
+
path = ::File.join(views, "#{data}.#{engine}")
|
351
|
+
Tilt[engine].new(path, 1, options)
|
352
|
+
end
|
353
|
+
when data.is_a?(Proc) || data.is_a?(String)
|
354
|
+
body = data.is_a?(String) ? Proc.new { data } : data
|
355
|
+
path, line = self.class.caller_locations.first
|
356
|
+
Tilt[engine].new(path, line.to_i, options, &body)
|
296
357
|
else
|
297
|
-
|
298
|
-
[ ::File.read(path), path, 1 ]
|
358
|
+
raise ArgumentError
|
299
359
|
end
|
300
|
-
when Proc
|
301
|
-
filename, line = self.class.caller_locations.first if filename.nil?
|
302
|
-
[ template.call, filename, line.to_i ]
|
303
|
-
when String
|
304
|
-
filename, line = self.class.caller_locations.first if filename.nil?
|
305
|
-
[ template, filename, line.to_i ]
|
306
|
-
else
|
307
|
-
raise ArgumentError
|
308
360
|
end
|
309
361
|
end
|
310
|
-
|
311
|
-
def lookup_layout(engine, template, views_dir)
|
312
|
-
lookup_template(engine, template, views_dir)
|
313
|
-
rescue Errno::ENOENT
|
314
|
-
nil
|
315
|
-
end
|
316
|
-
|
317
|
-
def render_erb(template, data, options, locals, &block)
|
318
|
-
original_out_buf = defined?(@_out_buf) && @_out_buf
|
319
|
-
data = data.call if data.kind_of? Proc
|
320
|
-
|
321
|
-
instance = ::ERB.new(data, nil, nil, '@_out_buf')
|
322
|
-
locals_assigns = locals.to_a.collect { |k,v| "#{k} = locals[:#{k}]" }
|
323
|
-
|
324
|
-
filename = options.delete(:filename) || '(__ERB__)'
|
325
|
-
line = options.delete(:line) || 1
|
326
|
-
line -= 1 if instance.src =~ /^#coding:/
|
327
|
-
|
328
|
-
render_binding = binding
|
329
|
-
eval locals_assigns.join("\n"), render_binding
|
330
|
-
eval instance.src, render_binding, filename, line
|
331
|
-
@_out_buf, result = original_out_buf, @_out_buf
|
332
|
-
result
|
333
|
-
end
|
334
|
-
|
335
|
-
def render_haml(template, data, options, locals, &block)
|
336
|
-
::Haml::Engine.new(data, options).render(self, locals, &block)
|
337
|
-
end
|
338
|
-
|
339
|
-
def render_sass(template, data, options, locals, &block)
|
340
|
-
::Sass::Engine.new(data, options).render
|
341
|
-
end
|
342
|
-
|
343
|
-
def render_builder(template, data, options, locals, &block)
|
344
|
-
options = { :indent => 2 }.merge(options)
|
345
|
-
filename = options.delete(:filename) || '<BUILDER>'
|
346
|
-
line = options.delete(:line) || 1
|
347
|
-
xml = ::Builder::XmlMarkup.new(options)
|
348
|
-
if data.respond_to?(:to_str)
|
349
|
-
eval data.to_str, binding, filename, line
|
350
|
-
elsif data.kind_of?(Proc)
|
351
|
-
data.call(xml)
|
352
|
-
end
|
353
|
-
xml.target!
|
354
|
-
end
|
355
|
-
|
356
|
-
def require_warn(engine)
|
357
|
-
sinatra_warn "auto-require of #{engine} is deprecated; add require '#{engine}' to your app."
|
358
|
-
require engine.downcase
|
359
|
-
end
|
360
362
|
end
|
361
363
|
|
362
364
|
# Base class for all Sinatra applications and middleware.
|
@@ -369,6 +371,7 @@ module Sinatra
|
|
369
371
|
|
370
372
|
def initialize(app=nil)
|
371
373
|
@app = app
|
374
|
+
@template_cache = Tilt::Cache.new
|
372
375
|
yield self if block_given?
|
373
376
|
end
|
374
377
|
|
@@ -383,7 +386,8 @@ module Sinatra
|
|
383
386
|
@env = env
|
384
387
|
@request = Request.new(env)
|
385
388
|
@response = Response.new
|
386
|
-
@params =
|
389
|
+
@params = indifferent_params(@request.params)
|
390
|
+
@template_cache.clear if settings.reload_templates
|
387
391
|
|
388
392
|
invoke { dispatch! }
|
389
393
|
invoke { error_block!(response.status) }
|
@@ -417,8 +421,8 @@ module Sinatra
|
|
417
421
|
# Pass control to the next matching route.
|
418
422
|
# If there are no more matching routes, Sinatra will
|
419
423
|
# return a 404 response.
|
420
|
-
def pass
|
421
|
-
throw :pass
|
424
|
+
def pass(&block)
|
425
|
+
throw :pass, block
|
422
426
|
end
|
423
427
|
|
424
428
|
# Forward the request to the downstream app -- middleware only.
|
@@ -432,21 +436,21 @@ module Sinatra
|
|
432
436
|
end
|
433
437
|
|
434
438
|
private
|
435
|
-
# Run before filters
|
436
|
-
def
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
indifferent_params(@request.params)
|
441
|
-
else
|
442
|
-
nested_params(@request.params)
|
443
|
-
end
|
439
|
+
# Run before filters defined on the class and all superclasses.
|
440
|
+
def before_filter!(base=self.class)
|
441
|
+
before_filter!(base.superclass) if base.superclass.respond_to?(:before_filters)
|
442
|
+
base.before_filters.each { |block| instance_eval(&block) }
|
443
|
+
end
|
444
444
|
|
445
|
-
|
446
|
-
|
445
|
+
# Run after filters defined on the class and all superclasses.
|
446
|
+
def after_filter!(base=self.class)
|
447
|
+
after_filter!(base.superclass) if base.superclass.respond_to?(:after_filters)
|
448
|
+
base.after_filters.each { |block| instance_eval(&block) }
|
449
|
+
end
|
447
450
|
|
448
|
-
|
449
|
-
|
451
|
+
# Run routes defined on the class and all superclasses.
|
452
|
+
def route!(base=self.class, pass_block=nil)
|
453
|
+
if routes = base.routes[@request.request_method]
|
450
454
|
original_params = @params
|
451
455
|
path = unescape(@request.path_info)
|
452
456
|
|
@@ -471,15 +475,25 @@ module Sinatra
|
|
471
475
|
@params = original_params.merge(params)
|
472
476
|
@block_params = values
|
473
477
|
|
474
|
-
catch(:pass) do
|
478
|
+
pass_block = catch(:pass) do
|
475
479
|
conditions.each { |cond|
|
476
480
|
throw :pass if instance_eval(&cond) == false }
|
477
481
|
route_eval(&block)
|
478
482
|
end
|
479
483
|
end
|
480
484
|
end
|
485
|
+
|
486
|
+
@params = original_params
|
487
|
+
end
|
488
|
+
|
489
|
+
# Run routes defined in superclass.
|
490
|
+
if base.superclass.respond_to?(:routes)
|
491
|
+
route! base.superclass, pass_block
|
492
|
+
return
|
481
493
|
end
|
482
494
|
|
495
|
+
route_eval(&pass_block) if pass_block
|
496
|
+
|
483
497
|
route_missing
|
484
498
|
end
|
485
499
|
|
@@ -501,6 +515,20 @@ module Sinatra
|
|
501
515
|
end
|
502
516
|
end
|
503
517
|
|
518
|
+
# Attempt to serve static files from public directory. Throws :halt when
|
519
|
+
# a matching file is found, returns nil otherwise.
|
520
|
+
def static!
|
521
|
+
return if (public_dir = settings.public).nil?
|
522
|
+
public_dir = File.expand_path(public_dir)
|
523
|
+
|
524
|
+
path = File.expand_path(public_dir + unescape(request.path_info))
|
525
|
+
return if path[0, public_dir.length] != public_dir
|
526
|
+
return unless File.file?(path)
|
527
|
+
|
528
|
+
env['sinatra.static_file'] = path
|
529
|
+
send_file path, :disposition => nil
|
530
|
+
end
|
531
|
+
|
504
532
|
# Enable string or symbol key access to the nested params hash.
|
505
533
|
def indifferent_params(params)
|
506
534
|
params = indifferent_hash.merge(params)
|
@@ -510,23 +538,6 @@ module Sinatra
|
|
510
538
|
end
|
511
539
|
end
|
512
540
|
|
513
|
-
# Recursively replace the params hash with a nested indifferent
|
514
|
-
# hash. Rack 1.0 has a built in implementation of this method - remove
|
515
|
-
# this once Rack 1.0 is required.
|
516
|
-
def nested_params(params)
|
517
|
-
return indifferent_hash.merge(params) if !params.keys.join.include?('[')
|
518
|
-
params.inject indifferent_hash do |res, (key,val)|
|
519
|
-
if key.include?('[')
|
520
|
-
head = key.split(/[\]\[]+/)
|
521
|
-
last = head.pop
|
522
|
-
head.inject(res){ |hash,k| hash[k] ||= indifferent_hash }[last] = val
|
523
|
-
else
|
524
|
-
res[key] = val
|
525
|
-
end
|
526
|
-
res
|
527
|
-
end
|
528
|
-
end
|
529
|
-
|
530
541
|
def indifferent_hash
|
531
542
|
Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
532
543
|
end
|
@@ -566,25 +577,30 @@ module Sinatra
|
|
566
577
|
|
567
578
|
# Dispatch a request with error handling.
|
568
579
|
def dispatch!
|
580
|
+
static! if settings.static? && (request.get? || request.head?)
|
581
|
+
before_filter!
|
569
582
|
route!
|
570
583
|
rescue NotFound => boom
|
571
584
|
handle_not_found!(boom)
|
572
585
|
rescue ::Exception => boom
|
573
586
|
handle_exception!(boom)
|
587
|
+
ensure
|
588
|
+
after_filter! unless env['sinatra.static_file']
|
574
589
|
end
|
575
590
|
|
576
591
|
def handle_not_found!(boom)
|
577
|
-
@env['sinatra.error']
|
578
|
-
@response.status
|
579
|
-
@response.
|
592
|
+
@env['sinatra.error'] = boom
|
593
|
+
@response.status = 404
|
594
|
+
@response.headers['X-Cascade'] = 'pass'
|
595
|
+
@response.body = ['<h1>Not Found</h1>']
|
580
596
|
error_block! boom.class, NotFound
|
581
597
|
end
|
582
598
|
|
583
599
|
def handle_exception!(boom)
|
584
600
|
@env['sinatra.error'] = boom
|
585
601
|
|
586
|
-
dump_errors!(boom) if
|
587
|
-
raise boom if
|
602
|
+
dump_errors!(boom) if settings.dump_errors?
|
603
|
+
raise boom if settings.raise_errors? || settings.show_exceptions?
|
588
604
|
|
589
605
|
@response.status = 500
|
590
606
|
error_block! boom.class, Exception
|
@@ -592,11 +608,16 @@ module Sinatra
|
|
592
608
|
|
593
609
|
# Find an custom error block for the key(s) specified.
|
594
610
|
def error_block!(*keys)
|
595
|
-
errmap = self.class.errors
|
596
611
|
keys.each do |key|
|
597
|
-
|
598
|
-
|
599
|
-
|
612
|
+
base = self.class
|
613
|
+
while base.respond_to?(:errors)
|
614
|
+
if block = base.errors[key]
|
615
|
+
# found a handler, eval and return result
|
616
|
+
res = instance_eval(&block)
|
617
|
+
return res
|
618
|
+
else
|
619
|
+
base = base.superclass
|
620
|
+
end
|
600
621
|
end
|
601
622
|
end
|
602
623
|
nil
|
@@ -606,11 +627,11 @@ module Sinatra
|
|
606
627
|
backtrace = clean_backtrace(boom.backtrace)
|
607
628
|
msg = ["#{boom.class} - #{boom.message}:",
|
608
629
|
*backtrace].join("\n ")
|
609
|
-
@env['rack.errors'].
|
630
|
+
@env['rack.errors'].puts(msg)
|
610
631
|
end
|
611
632
|
|
612
633
|
def clean_backtrace(trace)
|
613
|
-
return trace unless
|
634
|
+
return trace unless settings.clean_trace?
|
614
635
|
|
615
636
|
trace.reject { |line|
|
616
637
|
line =~ /lib\/sinatra.*\.rb/ ||
|
@@ -618,18 +639,43 @@ module Sinatra
|
|
618
639
|
}.map! { |line| line.gsub(/^\.\//, '') }
|
619
640
|
end
|
620
641
|
|
621
|
-
@routes = {}
|
622
|
-
@filters = []
|
623
|
-
@conditions = []
|
624
|
-
@templates = {}
|
625
|
-
@middleware = []
|
626
|
-
@errors = {}
|
627
|
-
@prototype = nil
|
628
|
-
@extensions = []
|
629
|
-
|
630
642
|
class << self
|
631
|
-
|
632
|
-
|
643
|
+
attr_reader :routes, :before_filters, :after_filters, :templates, :errors
|
644
|
+
|
645
|
+
def reset!
|
646
|
+
@conditions = []
|
647
|
+
@routes = {}
|
648
|
+
@before_filters = []
|
649
|
+
@after_filters = []
|
650
|
+
@errors = {}
|
651
|
+
@middleware = []
|
652
|
+
@prototype = nil
|
653
|
+
@extensions = []
|
654
|
+
|
655
|
+
if superclass.respond_to?(:templates)
|
656
|
+
@templates = Hash.new { |hash,key| superclass.templates[key] }
|
657
|
+
else
|
658
|
+
@templates = {}
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
# Extension modules registered on this class and all superclasses.
|
663
|
+
def extensions
|
664
|
+
if superclass.respond_to?(:extensions)
|
665
|
+
(@extensions + superclass.extensions).uniq
|
666
|
+
else
|
667
|
+
@extensions
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
# Middleware used in this class and all superclasses.
|
672
|
+
def middleware
|
673
|
+
if superclass.respond_to?(:middleware)
|
674
|
+
superclass.middleware + @middleware
|
675
|
+
else
|
676
|
+
@middleware
|
677
|
+
end
|
678
|
+
end
|
633
679
|
|
634
680
|
# Sets an option to the given value. If the value is a proc,
|
635
681
|
# the proc will be called every time the option is accessed.
|
@@ -637,7 +683,7 @@ module Sinatra
|
|
637
683
|
if value.kind_of?(Proc)
|
638
684
|
metadef(option, &value)
|
639
685
|
metadef("#{option}?") { !!__send__(option) }
|
640
|
-
metadef("#{option}=") { |val|
|
686
|
+
metadef("#{option}=") { |val| set(option, Proc.new{val}) }
|
641
687
|
elsif value == self && option.respond_to?(:to_hash)
|
642
688
|
option.to_hash.each { |k,v| set(k, v) }
|
643
689
|
elsif respond_to?("#{option}=")
|
@@ -662,11 +708,7 @@ module Sinatra
|
|
662
708
|
# class, or an HTTP status code to specify which errors should be
|
663
709
|
# handled.
|
664
710
|
def error(codes=Exception, &block)
|
665
|
-
|
666
|
-
codes.each { |err| error(err, &block) }
|
667
|
-
else
|
668
|
-
@errors[codes] = block
|
669
|
-
end
|
711
|
+
Array(codes).each { |code| @errors[code] = block }
|
670
712
|
end
|
671
713
|
|
672
714
|
# Sugar for `error(404) { ... }`
|
@@ -677,7 +719,7 @@ module Sinatra
|
|
677
719
|
# Define a named template. The block must return the template source.
|
678
720
|
def template(name, &block)
|
679
721
|
filename, line = caller_locations.first
|
680
|
-
templates[name] =
|
722
|
+
templates[name] = [block, filename, line.to_i]
|
681
723
|
end
|
682
724
|
|
683
725
|
# Define the layout template. The block must return the template source.
|
@@ -685,12 +727,6 @@ module Sinatra
|
|
685
727
|
template name, &block
|
686
728
|
end
|
687
729
|
|
688
|
-
def use_in_file_templates!(file=nil)
|
689
|
-
sinatra_warn "use_in_file_templates! is deprecated; " \
|
690
|
-
"use enable :inline_templates instead"
|
691
|
-
set :inline_templates, file
|
692
|
-
end
|
693
|
-
|
694
730
|
# Load embeded templates from the file; uses the caller's __FILE__
|
695
731
|
# when no file is specified.
|
696
732
|
def inline_templates=(file=nil)
|
@@ -710,7 +746,7 @@ module Sinatra
|
|
710
746
|
lines += 1
|
711
747
|
if line =~ /^@@\s*(.*)/
|
712
748
|
template = ''
|
713
|
-
templates[$1.to_sym] =
|
749
|
+
templates[$1.to_sym] = [template, file, lines]
|
714
750
|
elsif template
|
715
751
|
template << line
|
716
752
|
end
|
@@ -726,16 +762,18 @@ module Sinatra
|
|
726
762
|
Rack::Mime::MIME_TYPES[type] = value
|
727
763
|
end
|
728
764
|
|
729
|
-
|
730
|
-
|
731
|
-
|
765
|
+
# Define a before filter; runs before all requests within the same
|
766
|
+
# context as route handlers and may access/modify the request and
|
767
|
+
# response.
|
768
|
+
def before(&block)
|
769
|
+
@before_filters << block
|
732
770
|
end
|
733
771
|
|
734
|
-
# Define
|
735
|
-
#
|
736
|
-
#
|
737
|
-
def
|
738
|
-
@
|
772
|
+
# Define an after filter; runs after all requests within the same
|
773
|
+
# context as route handlers and may access/modify the request and
|
774
|
+
# response.
|
775
|
+
def after(&block)
|
776
|
+
@after_filters << block
|
739
777
|
end
|
740
778
|
|
741
779
|
# Add a route condition. The route is considered non-matching when the
|
@@ -806,14 +844,14 @@ module Sinatra
|
|
806
844
|
unbound_method = instance_method("#{verb} #{path}")
|
807
845
|
block =
|
808
846
|
if block.arity != 0
|
809
|
-
|
847
|
+
proc { unbound_method.bind(self).call(*@block_params) }
|
810
848
|
else
|
811
|
-
|
849
|
+
proc { unbound_method.bind(self).call }
|
812
850
|
end
|
813
851
|
|
814
852
|
invoke_hook(:route_added, verb, path, block)
|
815
853
|
|
816
|
-
(routes[verb] ||= []).
|
854
|
+
(@routes[verb] ||= []).
|
817
855
|
push([pattern, keys, conditions, block]).last
|
818
856
|
end
|
819
857
|
|
@@ -856,10 +894,6 @@ module Sinatra
|
|
856
894
|
include(*extensions) if extensions.any?
|
857
895
|
end
|
858
896
|
|
859
|
-
def extensions
|
860
|
-
(@extensions + (superclass.extensions rescue [])).uniq
|
861
|
-
end
|
862
|
-
|
863
897
|
def register(*extensions, &block)
|
864
898
|
extensions << Module.new(&block) if block_given?
|
865
899
|
@extensions += extensions
|
@@ -899,6 +933,7 @@ module Sinatra
|
|
899
933
|
server.respond_to?(:stop!) ? server.stop! : server.stop
|
900
934
|
puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
|
901
935
|
end
|
936
|
+
set :running, true
|
902
937
|
end
|
903
938
|
rescue Errno::EADDRINUSE => e
|
904
939
|
puts "== Someone is already performing on port #{port}!"
|
@@ -914,12 +949,12 @@ module Sinatra
|
|
914
949
|
# an instance of the class new was called on.
|
915
950
|
def new(*args, &bk)
|
916
951
|
builder = Rack::Builder.new
|
917
|
-
builder.use Rack::Session::Cookie if sessions?
|
952
|
+
builder.use Rack::Session::Cookie if sessions?
|
918
953
|
builder.use Rack::CommonLogger if logging?
|
919
|
-
builder.use Rack::MethodOverride if
|
954
|
+
builder.use Rack::MethodOverride if methodoverride?
|
920
955
|
builder.use ShowExceptions if show_exceptions?
|
956
|
+
middleware.each { |c,a,b| builder.use(c, *a, &b) }
|
921
957
|
|
922
|
-
@middleware.each { |c,a,b| builder.use(c, *a, &b) }
|
923
958
|
builder.run super
|
924
959
|
builder.to_app
|
925
960
|
end
|
@@ -928,25 +963,6 @@ module Sinatra
|
|
928
963
|
synchronize { prototype.call(env) }
|
929
964
|
end
|
930
965
|
|
931
|
-
def reset!(base=superclass)
|
932
|
-
@routes = base.dupe_routes
|
933
|
-
@templates = base.templates.dup
|
934
|
-
@conditions = []
|
935
|
-
@filters = base.filters.dup
|
936
|
-
@errors = base.errors.dup
|
937
|
-
@middleware = base.middleware.dup
|
938
|
-
@prototype = nil
|
939
|
-
@extensions = []
|
940
|
-
end
|
941
|
-
|
942
|
-
protected
|
943
|
-
def dupe_routes
|
944
|
-
routes.inject({}) do |hash,(request_method,routes)|
|
945
|
-
hash[request_method] = routes.dup
|
946
|
-
hash
|
947
|
-
end
|
948
|
-
end
|
949
|
-
|
950
966
|
private
|
951
967
|
def detect_rack_handler
|
952
968
|
servers = Array(self.server)
|
@@ -961,7 +977,7 @@ module Sinatra
|
|
961
977
|
end
|
962
978
|
|
963
979
|
def inherited(subclass)
|
964
|
-
subclass.reset!
|
980
|
+
subclass.reset!
|
965
981
|
super
|
966
982
|
end
|
967
983
|
|
@@ -981,11 +997,12 @@ module Sinatra
|
|
981
997
|
|
982
998
|
public
|
983
999
|
CALLERS_TO_IGNORE = [
|
984
|
-
/\/sinatra(\/(base|main|showexceptions
|
1000
|
+
/\/sinatra(\/(base|main|showexceptions))?\.rb$/, # all sinatra code
|
1001
|
+
/lib\/tilt.*\.rb$/, # all tilt code
|
985
1002
|
/\(.*\)/, # generated code
|
986
1003
|
/custom_require\.rb$/, # rubygems require hacks
|
987
1004
|
/active_support/, # active_support require hacks
|
988
|
-
]
|
1005
|
+
]
|
989
1006
|
|
990
1007
|
# add rubinius (and hopefully other VM impls) ignore patterns ...
|
991
1008
|
CALLERS_TO_IGNORE.concat(RUBY_IGNORE_CALLERS) if defined?(RUBY_IGNORE_CALLERS)
|
@@ -1004,6 +1021,8 @@ module Sinatra
|
|
1004
1021
|
end
|
1005
1022
|
end
|
1006
1023
|
|
1024
|
+
reset!
|
1025
|
+
|
1007
1026
|
set :environment, (ENV['RACK_ENV'] || :development).to_sym
|
1008
1027
|
set :raise_errors, Proc.new { !development? }
|
1009
1028
|
set :dump_errors, Proc.new { development? }
|
@@ -1011,9 +1030,10 @@ module Sinatra
|
|
1011
1030
|
set :clean_trace, true
|
1012
1031
|
set :sessions, false
|
1013
1032
|
set :logging, false
|
1014
|
-
set :
|
1033
|
+
set :methodoverride, false
|
1015
1034
|
|
1016
|
-
set :run, false
|
1035
|
+
set :run, false # start server via at-exit hook?
|
1036
|
+
set :running, false # is the built-in server running now?
|
1017
1037
|
set :server, %w[thin mongrel webrick]
|
1018
1038
|
set :host, '0.0.0.0'
|
1019
1039
|
set :port, 4567
|
@@ -1021,24 +1041,11 @@ module Sinatra
|
|
1021
1041
|
set :app_file, nil
|
1022
1042
|
set :root, Proc.new { app_file && File.expand_path(File.dirname(app_file)) }
|
1023
1043
|
set :views, Proc.new { root && File.join(root, 'views') }
|
1024
|
-
set :
|
1025
|
-
set :static, Proc.new { self.public && File.exist?(self.public) }
|
1044
|
+
set :reload_templates, Proc.new { !development? }
|
1026
1045
|
set :lock, false
|
1027
1046
|
|
1028
|
-
|
1029
|
-
|
1030
|
-
alias_method :methodoverride=, :method_override=
|
1031
|
-
end
|
1032
|
-
|
1033
|
-
# static files route
|
1034
|
-
get(/.*[^\/]$/) do
|
1035
|
-
pass unless options.static? && options.public?
|
1036
|
-
public_dir = File.expand_path(options.public)
|
1037
|
-
path = File.expand_path(public_dir + unescape(request.path_info))
|
1038
|
-
pass if path[0, public_dir.length] != public_dir
|
1039
|
-
pass unless File.file?(path)
|
1040
|
-
send_file path, :disposition => nil
|
1041
|
-
end
|
1047
|
+
set :public, Proc.new { root && File.join(root, 'public') }
|
1048
|
+
set :static, Proc.new { self.public && File.exist?(self.public) }
|
1042
1049
|
|
1043
1050
|
error ::Exception do
|
1044
1051
|
response.status = 500
|
@@ -1080,24 +1087,6 @@ module Sinatra
|
|
1080
1087
|
end
|
1081
1088
|
end
|
1082
1089
|
|
1083
|
-
# Deprecated as base class for non-top-level apps. Subclass
|
1084
|
-
# Sinatra::Base instead and set options as needed.
|
1085
|
-
class Default < Base
|
1086
|
-
set :raise_errors, Proc.new { test? }
|
1087
|
-
set :dump_errors, true
|
1088
|
-
set :sessions, false
|
1089
|
-
set :logging, Proc.new { ! test? }
|
1090
|
-
set :method_override, true
|
1091
|
-
set :run, Proc.new { ! test? }
|
1092
|
-
set :static, true
|
1093
|
-
|
1094
|
-
def self.inherited(subclass)
|
1095
|
-
sinatra_warn 'Sinatra::Default is deprecated; ' \
|
1096
|
-
'subclass Sinatra::Base instead'
|
1097
|
-
super
|
1098
|
-
end
|
1099
|
-
end
|
1100
|
-
|
1101
1090
|
# Execution context for classic style (top-level) applications. All
|
1102
1091
|
# DSL methods executed on main are delegated to this class.
|
1103
1092
|
#
|
@@ -1110,7 +1099,7 @@ module Sinatra
|
|
1110
1099
|
set :dump_errors, true
|
1111
1100
|
set :sessions, false
|
1112
1101
|
set :logging, Proc.new { ! test? }
|
1113
|
-
set :
|
1102
|
+
set :methodoverride, true
|
1114
1103
|
set :run, Proc.new { ! test? }
|
1115
1104
|
set :static, true
|
1116
1105
|
|
@@ -1136,10 +1125,10 @@ module Sinatra
|
|
1136
1125
|
end
|
1137
1126
|
end
|
1138
1127
|
|
1139
|
-
delegate :get, :put, :post, :delete, :head, :template, :layout,
|
1140
|
-
:
|
1141
|
-
:
|
1142
|
-
:
|
1128
|
+
delegate :get, :put, :post, :delete, :head, :template, :layout,
|
1129
|
+
:before, :after, :error, :not_found, :configure, :set, :mime_type,
|
1130
|
+
:enable, :disable, :use, :development?, :test?, :production?,
|
1131
|
+
:helpers, :settings
|
1143
1132
|
end
|
1144
1133
|
|
1145
1134
|
# Create a new Sinatra application. The block is evaluated in the new app's
|
@@ -1160,13 +1149,3 @@ module Sinatra
|
|
1160
1149
|
Application.helpers(*extensions, &block)
|
1161
1150
|
end
|
1162
1151
|
end
|
1163
|
-
|
1164
|
-
class String #:nodoc:
|
1165
|
-
# Define String#each under 1.9 for Rack compatibility. This should be
|
1166
|
-
# removed once Rack is fully 1.9 compatible.
|
1167
|
-
alias_method :each, :each_line unless ''.respond_to? :each
|
1168
|
-
|
1169
|
-
# Define String#bytesize as an alias to String#length for Ruby 1.8.6 and
|
1170
|
-
# earlier.
|
1171
|
-
alias_method :bytesize, :length unless ''.respond_to? :bytesize
|
1172
|
-
end
|