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.

Files changed (67) hide show
  1. data/CHANGES +83 -29
  2. data/README.jp.rdoc +552 -0
  3. data/README.rdoc +31 -9
  4. data/Rakefile +73 -91
  5. data/lib/sinatra.rb +0 -1
  6. data/lib/sinatra/base.rb +248 -269
  7. data/lib/sinatra/main.rb +3 -11
  8. data/lib/sinatra/tilt.rb +509 -0
  9. data/sinatra.gemspec +15 -49
  10. data/test/erubis_test.rb +82 -0
  11. data/test/extensions_test.rb +1 -1
  12. data/test/filter_test.rb +125 -3
  13. data/test/helpers_test.rb +59 -2
  14. data/test/mapped_error_test.rb +31 -0
  15. data/test/middleware_test.rb +1 -1
  16. data/test/request_test.rb +15 -0
  17. data/test/routing_test.rb +76 -0
  18. data/test/{options_test.rb → settings_test.rb} +46 -50
  19. data/test/static_test.rb +13 -0
  20. data/test/templates_test.rb +43 -10
  21. data/test/views/error.erubis +3 -0
  22. data/test/views/hello.erubis +1 -0
  23. data/test/views/layout2.erubis +2 -0
  24. metadata +61 -88
  25. data/compat/app_test.rb +0 -282
  26. data/compat/application_test.rb +0 -262
  27. data/compat/builder_test.rb +0 -101
  28. data/compat/compat_test.rb +0 -12
  29. data/compat/custom_error_test.rb +0 -62
  30. data/compat/erb_test.rb +0 -136
  31. data/compat/events_test.rb +0 -78
  32. data/compat/filter_test.rb +0 -30
  33. data/compat/haml_test.rb +0 -237
  34. data/compat/helper.rb +0 -34
  35. data/compat/mapped_error_test.rb +0 -72
  36. data/compat/pipeline_test.rb +0 -45
  37. data/compat/public/foo.xml +0 -1
  38. data/compat/sass_test.rb +0 -67
  39. data/compat/sessions_test.rb +0 -42
  40. data/compat/streaming_test.rb +0 -133
  41. data/compat/sym_params_test.rb +0 -18
  42. data/compat/template_test.rb +0 -30
  43. data/compat/use_in_file_templates_test.rb +0 -47
  44. data/compat/views/foo.builder +0 -1
  45. data/compat/views/foo.erb +0 -1
  46. data/compat/views/foo.haml +0 -1
  47. data/compat/views/foo.sass +0 -2
  48. data/compat/views/foo_layout.erb +0 -2
  49. data/compat/views/foo_layout.haml +0 -2
  50. data/compat/views/layout_test/foo.builder +0 -1
  51. data/compat/views/layout_test/foo.erb +0 -1
  52. data/compat/views/layout_test/foo.haml +0 -1
  53. data/compat/views/layout_test/foo.sass +0 -2
  54. data/compat/views/layout_test/layout.builder +0 -3
  55. data/compat/views/layout_test/layout.erb +0 -1
  56. data/compat/views/layout_test/layout.haml +0 -1
  57. data/compat/views/layout_test/layout.sass +0 -2
  58. data/compat/views/no_layout/no_layout.builder +0 -1
  59. data/compat/views/no_layout/no_layout.haml +0 -1
  60. data/lib/sinatra/compat.rb +0 -258
  61. data/lib/sinatra/test.rb +0 -129
  62. data/lib/sinatra/test/bacon.rb +0 -19
  63. data/lib/sinatra/test/rspec.rb +0 -13
  64. data/lib/sinatra/test/spec.rb +0 -11
  65. data/lib/sinatra/test/unit.rb +0 -13
  66. data/test/render_backtrace_test.rb +0 -145
  67. data/test/test_test.rb +0 -155
@@ -1,6 +1,6 @@
1
1
  = Sinatra
2
2
 
3
- Sinatra is a DSL for quickly creating web-applications in Ruby with minimal
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 during a before filter or route use:
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 before filter. The exception object can be obtained from the
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/0.9.5/lib/sinatra/base.rb#L1124-1143]
548
- being {included into the main namespace}[http://github.com/sinatra/sinatra/blob/0.9.5/lib/sinatra/main.rb#L25].
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://www.sinatrarb.com/] - Additional documentation,
614
+ * {Project Website}[http://sinatra.github.com/] - Additional documentation,
593
615
  news, and links to other resources.
594
- * {Contributing}[http://www.sinatrarb.com/contributing] - Find a bug? Need
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/topics]
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 => [:test, :compat]
5
+ task :default => :test
6
6
  task :spec => :test
7
7
 
8
- # SPECS ===============================================================
8
+ def source_version
9
+ line = File.read('lib/sinatra/base.rb')[/^\s*VERSION = .*/]
10
+ line.match(/.*VERSION = '(.*)'/)[1]
11
+ end
9
12
 
10
- task(:test) { puts "==> Running main test suite" }
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
- desc "Run < 0.9.x compatibility specs"
18
- task :compat do
19
- begin
20
- require 'mocha'
21
- require 'test/spec'
22
- at_exit { exit 0 } # disable test-spec at_exit runner
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
- # PACKAGING ============================================================
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
- # Gemspec Helpers ====================================================
54
+ # PACKAGING ============================================================
105
55
 
106
- def source_version
107
- line = File.read('lib/sinatra/base.rb')[/^\s*VERSION = .*/]
108
- line.match(/.*VERSION = '(.*)'/)[1]
109
- end
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
- task 'sinatra.gemspec' => FileList['{lib,test,compat}/**','Rakefile','CHANGES','*.rdoc'] do |f|
112
- # read spec file and split out manifest section
113
- spec = File.read(f.name)
114
- head, manifest, tail = spec.split(" # = MANIFEST =\n")
115
- # replace version and date
116
- head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
117
- head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
118
- # determine file list from git ls-files
119
- files = `git ls-files`.
120
- split("\n").
121
- sort.
122
- reject{ |file| file =~ /^\./ }.
123
- reject { |file| file =~ /^doc/ }.
124
- map{ |file| " #{file}" }.
125
- join("\n")
126
- # piece file back together and write...
127
- manifest = " s.files = %w[\n#{files}\n ]\n"
128
- spec = [head,manifest,tail].join(" # = MANIFEST =\n")
129
- File.open(f.name, 'w') { |io| io.write(spec) }
130
- puts "updated #{f.name}"
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
@@ -3,6 +3,5 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
3
 
4
4
  require 'sinatra/base'
5
5
  require 'sinatra/main'
6
- require 'sinatra/compat'
7
6
 
8
7
  enable :inline_templates
@@ -5,34 +5,41 @@ require 'rack'
5
5
  require 'rack/builder'
6
6
  require 'sinatra/showexceptions'
7
7
 
8
- # Like Kernel#warn but outputs the location that triggered the warning.
9
- def sinatra_warn(*message) #:nodoc:
10
- line = caller.
11
- detect { |line| line !~ /(?:lib\/sinatra\/|__DELEGATE__)/ }.
12
- sub(/:in .*/, '')
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.9.6'
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
- # Override Rack 0.9.x's #params implementation (see #72 in lighthouse)
32
- def params
33
- self.GET.update(self.POST)
34
- rescue EOFError, Errno::ESPIPE
35
- self.GET
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 + part.bytesize }.to_s
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 a the name of a template
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 haml(template, options={}, locals={})
245
- require_warn('Haml') unless defined?(::Haml::Engine)
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 = lambda { block } if template.nil?
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, template, options={}, locals={})
315
+ def render(engine, data, options={}, locals={}, &block)
267
316
  # merge app-level options
268
- options = self.class.send(engine).merge(options) if self.class.respond_to?(engine)
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
- data, options[:filename], options[:line] = lookup_template(engine, template, views)
278
- output = __send__("render_#{engine}", template, data, options, locals)
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
- data, options[:filename], options[:line] = lookup_layout(engine, layout, views)
283
- if data
284
- output = __send__("render_#{engine}", layout, data, options, locals) { 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 lookup_template(engine, template, views_dir, filename = nil, line = nil)
292
- case template
293
- when Symbol
294
- if cached = self.class.templates[template]
295
- lookup_template(engine, cached[:template], views_dir, cached[:filename], cached[:line])
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
- path = ::File.join(views_dir, "#{template}.#{engine}")
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 = nil
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 and then locate and run a matching route.
436
- def route!
437
- # enable nested params in Rack < 1.0; allow indifferent access
438
- @params =
439
- if Rack::Utils.respond_to?(:parse_nested_query)
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
- # before filters
446
- self.class.filters.each { |block| instance_eval(&block) }
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
- # routes
449
- if routes = self.class.routes[@request.request_method]
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'] = boom
578
- @response.status = 404
579
- @response.body = ['<h1>Not Found</h1>']
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 options.dump_errors?
587
- raise boom if options.raise_errors? || options.show_exceptions?
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
- if block = errmap[key]
598
- res = instance_eval(&block)
599
- return res
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'].write(msg)
630
+ @env['rack.errors'].puts(msg)
610
631
  end
611
632
 
612
633
  def clean_backtrace(trace)
613
- return trace unless options.clean_trace?
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
- attr_accessor :routes, :filters, :conditions, :templates,
632
- :middleware, :errors
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| metadef(option, &Proc.new{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
- if codes.respond_to? :each
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] = { :filename => filename, :line => line, :template => block }
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] = { :filename => file, :line => lines, :template => template }
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
- def media_type(type, value=nil)
730
- sinatra_warn "media_type is deprecated; use mime_type instead"
731
- mime_type(type, value)
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 a before filter. Filters are run before all requests
735
- # within the same context as route handlers and may access/modify the
736
- # request and response.
737
- def before(&block)
738
- @filters << block
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
- lambda { unbound_method.bind(self).call(*@block_params) }
847
+ proc { unbound_method.bind(self).call(*@block_params) }
810
848
  else
811
- lambda { unbound_method.bind(self).call }
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? && !test?
952
+ builder.use Rack::Session::Cookie if sessions?
918
953
  builder.use Rack::CommonLogger if logging?
919
- builder.use Rack::MethodOverride if method_override?
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! self
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|compat))?\.rb$/, # all sinatra code
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
- ] unless self.const_defined?('CALLERS_TO_IGNORE')
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 :method_override, false
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 :public, Proc.new { root && File.join(root, 'public') }
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
- class << self
1029
- alias_method :methodoverride?, :method_override?
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 :method_override, true
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, :before,
1140
- :error, :not_found, :configures, :configure, :set, :set_option,
1141
- :set_options, :enable, :disable, :use, :development?, :test?,
1142
- :production?, :use_in_file_templates!, :helpers, :mime_type
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