sinatra 0.3.1 → 0.3.2

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.

@@ -79,7 +79,7 @@ User agent matching:
79
79
  # matches non-songbird browsers
80
80
  end
81
81
 
82
- = Static files
82
+ == Static files
83
83
 
84
84
  Put all of your static content in the ./public directory
85
85
 
@@ -260,91 +260,75 @@ on Array, Symbol, Fixnum, NilClass.
260
260
 
261
261
  == Configuration and Reloading
262
262
 
263
- Sinatra supports multiple environments and re-loading. Re-loading happens on
264
- every request when in :development. Wrap your configurations in
265
- <tt>configure</tt> (i.e. Database connections, Constants, etc.) to protect
266
- them from re-loading and to only work in certain environments.
263
+ Sinatra supports multiple environments and reloading. Reloading happens
264
+ before every request when running under the :development environment. Wrap
265
+ your configurations in <tt>configure</tt> (i.e. Database connections, Constants,
266
+ etc.) to protect them from reloading or to target specific environments.
267
267
 
268
268
  All environments:
269
269
 
270
270
  configure do
271
-
271
+ ...
272
272
  end
273
273
 
274
- Production
274
+ Production:
275
275
 
276
276
  configure :production do
277
-
277
+ ...
278
278
  end
279
279
 
280
280
  Two at a time:
281
281
 
282
282
  configure :production, :test do
283
-
283
+ ...
284
284
  end
285
285
 
286
286
  This is also really nifty for error handling.
287
287
 
288
- = Error handling
288
+ == Error handling
289
289
 
290
- == Not Found
290
+ Error handlers run inside the current Sinatra::EventContext instance, which
291
+ means you get all the goodies it has to offer (i.e. haml, erb, throw :halt,
292
+ etc.)
291
293
 
292
- Remember: These are run inside the Sinatra::EventContext which means you get
293
- all the goodies is has to offer (i.e. haml, erb, :halt, etc.)
294
+ === Not Found
294
295
 
295
- Whenever NotFound is raised this will be called
296
+ When Sinatra::NotFound is raised, the not_found handler is invoked:
296
297
 
297
298
  not_found do
298
299
  'This is nowhere to be found'
299
300
  end
300
301
 
301
- == Error
302
+ === Error
302
303
 
303
- By default +error+ will catch Sinatra::ServerError
304
+ By default, the +error+ handler is invoked on Sinatra::ServerError or when
305
+ an unknown error occurs.
304
306
 
305
- Sinatra will pass you the error via the 'sinatra.error' in request.env
307
+ The exception can be obtained from the 'sinatra.error' variable in
308
+ request.env.
306
309
 
307
310
  error do
308
311
  'Sorry there was a nasty error - ' + request.env['sinatra.error'].name
309
312
  end
310
313
 
311
- Custom error mapping:
314
+ Custom errors:
312
315
 
313
316
  error MyCustomError do
314
317
  'So what happened was...' + request.env['sinatra.error'].message
315
318
  end
316
319
 
317
- then if this happens:
320
+ Then, if this happens:
318
321
 
319
322
  get '/' do
320
323
  raise MyCustomError, 'something bad'
321
324
  end
322
325
 
323
- you gets this:
326
+ You get this:
324
327
 
325
328
  So what happened was... something bad
326
329
 
327
- one guess what this does ;)
328
-
329
- not_found do
330
- 'I have no clue what you're looking for'
331
- end
332
-
333
- Because Sinatra gives you a default <tt>not_found</tt> and <tt>error</tt> do
334
- :production that are secure. If you want to customize only for :production
335
- but want to keep the friendly helper screens for :development then do this:
336
-
337
- configure :production do
338
-
339
- not_found do
340
- "We're so sorry, but we don't what this is"
341
- end
342
-
343
- error do
344
- "Something really nasty happened. We're on it!"
345
- end
346
-
347
- end
330
+ Sinatra installs special not_found and error handlers when running under
331
+ the development.
348
332
 
349
333
  == Mime types
350
334
 
@@ -360,12 +344,9 @@ interface for Ruby web frameworks. One of Rack's most interesting capabilities
360
344
  for application developers is support for "middleware" -- components that sit
361
345
  between the server and your application monitoring and/or manipulating the
362
346
  HTTP request/response to provide various types of common functionality.
363
- What's more, middleware is portable between web frameworks, so middleware
364
- components developed under, e.g., Merb, can be used with Sinatra and vice
365
- versa.
366
347
 
367
- Sinatra makes building Rack middleware pipelines a cinch via a top-level +use+
368
- method:
348
+ Sinatra makes building Rack middleware pipelines a cinch via a top-level
349
+ +use+ method:
369
350
 
370
351
  require 'sinatra'
371
352
  require 'my_custom_middleware'
@@ -393,24 +374,12 @@ typically don't have to +use+ them explicitly.
393
374
 
394
375
  == Testing
395
376
 
396
- === Methods
397
-
398
- get_it path, params
399
- get_it path, params.merge(:env => { 'HTTP_HOST' => 'www.sinatrarb.com' }) or
400
- get_it path, params.merge(:env => { :host => 'www.sinatrarb.com' })
401
-
402
- RESTful:
403
-
404
- post_it '/foo', '<myxml></myxml>', 'HTTP_ACCEPT' => 'application/xml'
405
-
406
- also works with:
407
-
408
- get_it, post_it, put_it, delete_it, head_it
409
-
410
377
  === Test/Unit
411
378
 
412
- require 'my_sinatra_app'
379
+ require 'rubygems'
380
+ require 'sinatra'
413
381
  require 'sinatra/test/unit'
382
+ require 'my_sinatra_app'
414
383
 
415
384
  class MyAppTest < Test::Unit::TestCase
416
385
 
@@ -428,31 +397,52 @@ also works with:
428
397
 
429
398
  end
430
399
 
431
- === Specs
400
+ === Test/Spec
432
401
 
433
- require 'my_sinatra_app'
402
+ require 'rubygems'
403
+ require 'sinatra'
434
404
  require 'sinatra/test/spec'
405
+ require 'my_sinatra_app'
435
406
 
436
- context 'My app'
407
+ describe 'My app' do
437
408
 
438
- should "show a default page" do
409
+ it "should show a default page" do
439
410
  get_it '/'
440
411
  should.be.ok
441
412
  body.should.equal 'My Default Page!'
442
413
  end
414
+
443
415
  ...
444
416
 
445
417
  end
446
418
 
447
- === Test Helpers
419
+ === RSpec
420
+
421
+ require 'rubygems'
422
+ require 'spec'
423
+ require 'sinatra'
424
+ require 'sinatra/test/rspec'
425
+ require 'my_sinatra_app'
426
+
427
+ describe 'My app' do
428
+ it 'should show a default page' do
429
+ get_it '/'
430
+ @response.should be_ok
431
+ @response.body.should == 'My Default Page!'
432
+ end
433
+
434
+ ...
435
+
436
+ end
448
437
 
449
- See Sinatra::Test::Methods
438
+ See Sinatra::Test::Methods for more information on +get_it+, +post_it+,
439
+ +put_it+, and friends.
450
440
 
451
441
  == Command line
452
442
 
453
- Run your sinatra file like:
443
+ Sinatra applications can be run directly:
454
444
 
455
- ruby myapp.rb [options]
445
+ ruby myapp.rb [-h] [-x] [-p PORT] [-e ENVIRONMENT]
456
446
 
457
447
  Options are:
458
448
 
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
+ require 'rubygems'
1
2
  require 'rake/clean'
3
+ require 'fileutils'
2
4
 
3
5
  task :default => :test
4
6
 
@@ -54,7 +56,7 @@ end
54
56
 
55
57
  # Rubyforge Release / Publish Tasks ==================================
56
58
 
57
- desc 'Publish API docs to rubyforge'
59
+ desc 'Publish website to rubyforge'
58
60
  task 'publish:doc' => 'doc/api/index.html' do
59
61
  sh 'scp -rp doc/* rubyforge.org:/var/www/gforge-projects/sinatra/'
60
62
  end
@@ -66,6 +68,77 @@ task 'publish:gem' => [package('.gem'), package('.tar.gz')] do |t|
66
68
  end
67
69
  end
68
70
 
71
+ # Website ============================================================
72
+ # Building docs requires HAML and the hanna gem:
73
+ # gem install mislav-hanna --source=http://gems.github.com
74
+
75
+ task 'doc' => ['doc:api','doc:site']
76
+
77
+ desc 'Generate Hanna RDoc under doc/api'
78
+ task 'doc:api' => ['doc/api/index.html']
79
+
80
+ file 'doc/api/index.html' => FileList['lib/**/*.rb','README.rdoc'] do |f|
81
+ rb_files = f.prerequisites
82
+ sh((<<-end).gsub(/\s+/, ' '))
83
+ hanna --charset utf8 \
84
+ --fmt html \
85
+ --inline-source \
86
+ --line-numbers \
87
+ --main README.rdoc \
88
+ --op doc/api \
89
+ --title 'Sinatra API Documentation' \
90
+ #{rb_files.join(' ')}
91
+ end
92
+ end
93
+ CLEAN.include 'doc/api'
94
+
95
+ def rdoc_to_html(file_name)
96
+ require 'rdoc/markup/to_html'
97
+ rdoc = RDoc::Markup::ToHtml.new
98
+ rdoc.convert(File.read(file_name))
99
+ end
100
+
101
+ def haml(locals={})
102
+ require 'haml'
103
+ template = File.read('doc/template.haml')
104
+ haml = Haml::Engine.new(template, :format => :html4, :attr_wrapper => '"')
105
+ haml.render(Object.new, locals)
106
+ end
107
+
108
+ desc 'Build website HTML and stuff'
109
+ task 'doc:site' => ['doc/index.html', 'doc/book.html']
110
+
111
+ file 'doc/index.html' => %w[README.rdoc doc/template.haml] do |file|
112
+ File.open(file.name, 'w') do |file|
113
+ file << haml(:title => 'Sinatra', :content => rdoc_to_html('README.rdoc'))
114
+ end
115
+ end
116
+ CLEAN.include 'doc/index.html'
117
+
118
+ file 'doc/book.html' => ['book/output/sinatra-book.html'] do |file|
119
+ File.open(file.name, 'w') do |file|
120
+ book_content = File.read('book/output/sinatra-book.html')
121
+ file << haml(:title => 'Sinatra Book', :content => book_content)
122
+ end
123
+ end
124
+ CLEAN.include 'doc/book.html'
125
+
126
+ file 'book/output/sinatra-book.html' => FileList['book/**'] do |f|
127
+ unless File.directory?('book')
128
+ sh 'git clone git://github.com/cschneid/sinatra-book.git book'
129
+ end
130
+ sh((<<-SH).strip.gsub(/\s+/, ' '))
131
+ cd book &&
132
+ git fetch origin &&
133
+ git rebase origin/master &&
134
+ thor book:build
135
+ SH
136
+ end
137
+ CLEAN.include 'book/output/sinatra-book.html'
138
+
139
+ desc 'Build the Sinatra book'
140
+ task 'doc:book' => ['book/output/sinatra-book.html']
141
+
69
142
  # Gemspec Helpers ====================================================
70
143
 
71
144
  file 'sinatra.gemspec' => FileList['{lib,test,images}/**','Rakefile'] do |f|
@@ -78,6 +151,7 @@ file 'sinatra.gemspec' => FileList['{lib,test,images}/**','Rakefile'] do |f|
78
151
  split("\n").
79
152
  sort.
80
153
  reject{ |file| file =~ /^\./ }.
154
+ reject { |file| file =~ /^doc/ }.
81
155
  map{ |file| " #{file}" }.
82
156
  join("\n")
83
157
  # piece file back together and write...
@@ -86,26 +160,3 @@ file 'sinatra.gemspec' => FileList['{lib,test,images}/**','Rakefile'] do |f|
86
160
  File.open(f.name, 'w') { |io| io.write(spec) }
87
161
  puts "updated #{f.name}"
88
162
  end
89
-
90
- # Hanna RDoc =========================================================
91
- #
92
- # Building docs requires the hanna gem:
93
- # gem install mislav-hanna --source=http://gems.github.com
94
-
95
- desc 'Generate Hanna RDoc under doc/api'
96
- task :doc => ['doc/api/index.html']
97
-
98
- file 'doc/api/index.html' => FileList['lib/**/*.rb','README.rdoc'] do |f|
99
- rb_files = f.prerequisites
100
- sh((<<-end).gsub(/\s+/, ' '))
101
- hanna --charset utf8 \
102
- --fmt html \
103
- --inline-source \
104
- --line-numbers \
105
- --main README.rdoc \
106
- --op doc/api \
107
- --title 'Sinatra API Documentation' \
108
- #{rb_files.join(' ')}
109
- end
110
- end
111
- CLEAN.include 'doc/api'
@@ -49,18 +49,13 @@ module Rack #:nodoc:
49
49
  module Utils
50
50
  extend self
51
51
  end
52
-
53
- module Handler
54
- autoload :Mongrel, ::File.dirname(__FILE__) + "/sinatra/rack/handler/mongrel"
55
- end
56
-
57
52
  end
58
53
 
59
54
 
60
55
  module Sinatra
61
56
  extend self
62
57
 
63
- VERSION = '0.3.0'
58
+ VERSION = '0.3.2'
64
59
 
65
60
  class NotFound < RuntimeError
66
61
  def self.code ; 404 ; end
@@ -202,20 +197,16 @@ module Sinatra
202
197
  class Static
203
198
  include Rack::Utils
204
199
 
205
- def invoke(request)
206
- return unless File.file?(
207
- Sinatra.application.options.public + unescape(request.path_info)
208
- )
209
- Result.new(block, {}, 200)
200
+ def initialize(app)
201
+ @app = app
210
202
  end
211
203
 
212
- def block
213
- Proc.new do
214
- send_file Sinatra.application.options.public +
215
- unescape(request.path_info), :disposition => nil
216
- end
204
+ def invoke(request)
205
+ path = @app.options.public + unescape(request.path_info)
206
+ return unless File.file?(path)
207
+ block = Proc.new { send_file path, :disposition => nil }
208
+ Result.new(block, {}, 200)
217
209
  end
218
-
219
210
  end
220
211
 
221
212
  # Methods for sending files and streams to the browser instead of rendering.
@@ -224,13 +215,12 @@ module Sinatra
224
215
  :type => 'application/octet-stream'.freeze,
225
216
  :disposition => 'attachment'.freeze,
226
217
  :stream => true,
227
- :buffer_size => 4096
218
+ :buffer_size => 8192
228
219
  }.freeze
229
220
 
230
221
  class MissingFile < RuntimeError; end
231
222
 
232
223
  class FileStreamer
233
-
234
224
  attr_reader :path, :options
235
225
 
236
226
  def initialize(path, options)
@@ -242,18 +232,17 @@ module Sinatra
242
232
  end
243
233
 
244
234
  def each
235
+ size = options[:buffer_size]
245
236
  File.open(path, 'rb') do |file|
246
- while buf = file.read(options[:buffer_size])
237
+ while buf = file.read(size)
247
238
  yield buf
248
239
  end
249
240
  end
250
241
  end
251
-
252
242
  end
253
243
 
254
244
  protected
255
-
256
- # Sends the file by streaming it 4096 bytes at a time. This way the
245
+ # Sends the file by streaming it 8192 bytes at a time. This way the
257
246
  # whole file doesn't need to be read into memory at once. This makes
258
247
  # it feasible to send even large files.
259
248
  #
@@ -274,7 +263,7 @@ module Sinatra
274
263
  # is read (true) or to read the entire file before sending (false).
275
264
  # Defaults to true.
276
265
  # * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used
277
- # to stream the file. Defaults to 4096.
266
+ # to stream the file. Defaults to 8192.
278
267
  # * <tt>:status</tt> - specifies the status code to send with the
279
268
  # response. Defaults to '200 OK'.
280
269
  # * <tt>:last_modified</tt> - an optional RFC 2616 formatted date value
@@ -319,12 +308,14 @@ module Sinatra
319
308
  options[:filename] ||= File.basename(path)
320
309
  options[:type] ||= Rack::File::MIME_TYPES[File.extname(options[:filename])[1..-1]] || 'text/plain'
321
310
  options[:last_modified] ||= File.mtime(path).httpdate
311
+ options[:stream] = true unless options.key?(:stream)
312
+ options[:buffer_size] ||= DEFAULT_SEND_FILE_OPTIONS[:buffer_size]
322
313
  send_file_headers! options
323
314
 
324
315
  if options[:stream]
325
316
  throw :halt, [options[:status] || 200, FileStreamer.new(path, options)]
326
317
  else
327
- File.open(path, 'rb') { |file| throw :halt, [options[:status] || 200, file.read] }
318
+ File.open(path, 'rb') { |file| throw :halt, [options[:status] || 200, [file.read]] }
328
319
  end
329
320
  end
330
321
 
@@ -359,7 +350,7 @@ module Sinatra
359
350
  # See +send_file+ for more information on HTTP Content-* headers and caching.
360
351
  def send_data(data, options = {}) #:doc:
361
352
  send_file_headers! options.merge(:length => data.size)
362
- throw :halt, [options[:status] || 200, data]
353
+ throw :halt, [options[:status] || 200, [data]]
363
354
  end
364
355
 
365
356
  private
@@ -1285,7 +1276,7 @@ module Sinatra
1285
1276
  # Called immediately after the application is initialized or reloaded to
1286
1277
  # register default events, templates, and error handlers.
1287
1278
  def load_default_configuration!
1288
- events[:get] << Static.new
1279
+ events[:get] << Static.new(self)
1289
1280
  configure do
1290
1281
  error do
1291
1282
  '<h1>Internal Server Error</h1>'
@@ -1467,9 +1458,7 @@ end
1467
1458
 
1468
1459
  at_exit do
1469
1460
  raise $! if $!
1470
- if Sinatra.application.options.run
1471
- Sinatra.run
1472
- end
1461
+ Sinatra.run if Sinatra.application.options.run
1473
1462
  end
1474
1463
 
1475
1464
  mime :xml, 'application/xml'
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
4
 
5
5
  s.name = 'sinatra'
6
- s.version = '0.3.1'
7
- s.date = "2008-09-08"
6
+ s.version = '0.3.2'
7
+ s.date = "2008-11-02"
8
8
 
9
9
  s.description = "Classy web-development dressed in a DSL"
10
10
  s.summary = "Classy web-development dressed in a DSL"
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
20
20
  images/404.png
21
21
  images/500.png
22
22
  lib/sinatra.rb
23
- lib/sinatra/rack/handler/mongrel.rb
24
23
  lib/sinatra/test/methods.rb
25
24
  lib/sinatra/test/rspec.rb
26
25
  lib/sinatra/test/spec.rb
@@ -70,7 +69,7 @@ Gem::Specification.new do |s|
70
69
  s.add_dependency 'rack', '>= 0.4.0'
71
70
 
72
71
  s.has_rdoc = true
73
- s.homepage = "http://sinatrarb.com"
72
+ s.homepage = "http://sinatra.rubyforge.org"
74
73
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sinatra", "--main", "README.rdoc"]
75
74
  s.require_paths = %w[lib]
76
75
  s.rubyforge_project = 'sinatra'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Mizerany
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-09-08 00:00:00 -07:00
12
+ date: 2008-11-02 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -39,7 +39,6 @@ files:
39
39
  - images/404.png
40
40
  - images/500.png
41
41
  - lib/sinatra.rb
42
- - lib/sinatra/rack/handler/mongrel.rb
43
42
  - lib/sinatra/test/methods.rb
44
43
  - lib/sinatra/test/rspec.rb
45
44
  - lib/sinatra/test/spec.rb
@@ -81,7 +80,7 @@ files:
81
80
  - test/views/no_layout/no_layout.builder
82
81
  - test/views/no_layout/no_layout.haml
83
82
  has_rdoc: true
84
- homepage: http://sinatrarb.com
83
+ homepage: http://sinatra.rubyforge.org
85
84
  post_install_message:
86
85
  rdoc_options:
87
86
  - --line-numbers
@@ -1,85 +0,0 @@
1
- require 'mongrel'
2
- require 'stringio'
3
-
4
-
5
- module Rack
6
- module Handler
7
- class Mongrel < ::Mongrel::HttpHandler
8
- def self.run(app, options={})
9
- server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0',
10
- options[:Port] || 8080)
11
- # Acts like Rack::URLMap, utilizing Mongrel's own path finding methods.
12
- # Use is similar to #run, replacing the app argument with a hash of
13
- # { path=>app, ... } or an instance of Rack::URLMap.
14
- if options[:map]
15
- if app.is_a? Hash
16
- app.each do |path, appl|
17
- path = '/'+path unless path[0] == ?/
18
- server.register(path, Rack::Handler::Mongrel.new(appl))
19
- end
20
- elsif app.is_a? URLMap
21
- app.instance_variable_get(:@mapping).each do |(host, path, appl)|
22
- next if !host.nil? && !options[:Host].nil? && options[:Host] != host
23
- path = '/'+path unless path[0] == ?/
24
- server.register(path, Rack::Handler::Mongrel.new(appl))
25
- end
26
- else
27
- raise ArgumentError, "first argument should be a Hash or URLMap"
28
- end
29
- else
30
- server.register('/', Rack::Handler::Mongrel.new(app))
31
- end
32
- yield server if block_given?
33
- server.run.join
34
- end
35
-
36
- def initialize(app)
37
- @app = app
38
- end
39
-
40
- def process(request, response)
41
- env = {}.replace(request.params)
42
- env.delete "HTTP_CONTENT_TYPE"
43
- env.delete "HTTP_CONTENT_LENGTH"
44
-
45
- env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
46
-
47
- env.update({"rack.version" => [0,1],
48
- "rack.input" => request.body || StringIO.new(""),
49
- "rack.errors" => STDERR,
50
-
51
- "rack.multithread" => true,
52
- "rack.multiprocess" => false, # ???
53
- "rack.run_once" => false,
54
-
55
- "rack.url_scheme" => "http",
56
- })
57
- env["QUERY_STRING"] ||= ""
58
- env.delete "PATH_INFO" if env["PATH_INFO"] == ""
59
-
60
- status, headers, body = @app.call(env)
61
-
62
- begin
63
- response.status = status.to_i
64
- headers.each { |k, vs|
65
- vs.each { |v|
66
- response.header[k] = v
67
- }
68
- }
69
- # taken from Merb until we have a better solution that conforms
70
- # to the Rack::Standard
71
- if Proc === body
72
- body.call(response)
73
- else
74
- body.each { |part|
75
- response.body << part
76
- }
77
- end
78
- response.finished
79
- ensure
80
- body.close if body.respond_to? :close
81
- end
82
- end
83
- end
84
- end
85
- end