bmizerany-sinatra 0.8.10 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,42 +1,28 @@
1
1
  = 0.9.0 (unreleased)
2
2
 
3
- * Works with and requires Rack >= 0.9.1
4
-
5
- * Multiple Sinatra applications can now co-exist peacefully within a
6
- single process. The new "Sinatra::Base" class can be subclassed to
7
- establish a blank-slate Rack application or middleware component.
8
- Documentation on using these features is forth-coming; the following
9
- provides the basic gist: http://gist.github.com/38605
10
-
11
- * Parameters with subscripts are now parsed into a nested/recursive
12
- Hash structure. e.g., "post[title]=Hello&post[body]=World" yields
13
- params: {'post' => {'title' => 'Hello', 'body' => 'World'}}.
14
-
15
- * Regular expressions may now be used in route pattens; captures are
16
- available at "params[:captures]".
17
-
18
3
  * New ":provides" route condition takes an array of mime types and
19
4
  matches only when an Accept request header is present with a
20
5
  corresponding type. [cypher]
21
6
 
22
- * New request-level "pass" method; immediately exits the current block
23
- and passes control to the next matching route.
7
+ * Work with and require Rack >= 0.9
8
+
9
+ * Regular expressions may now be used in route pattens; captures are
10
+ available at "params[:captures]".
24
11
 
25
12
  * The request-level "body" method now takes a block; evaluation is
26
13
  deferred until an attempt is made to read the body. The block must
27
14
  return a String or Array.
28
15
 
29
- * New "route conditions" system for attaching rules for when a route
30
- matches. The :agent and :host route options now use this system.
31
-
32
- * New "dump_errors" option controls whether the backtrace is dumped to
33
- rack.errors when an exception is raised from a route. The option is
34
- enabled by default for top-level apps.
35
-
36
16
  * Better default "app_file", "root", "public", and "views" location
37
17
  detection; changes to "root" and "app_file" automatically cascade to
38
18
  other options that depend on them.
39
19
 
20
+ * New "route conditions" system for attaching rules for when a route
21
+ matches. The :agent and :host route options now use this system.
22
+
23
+ * New request-level "pass" method; immediately exits the current block
24
+ and passes control to the next matching route.
25
+
40
26
  * Error mappings are now split into two distinct layers: exception
41
27
  mappings and custom error pages. Exception mappings are registered
42
28
  with "error(Exception)" and are run only when the app raises an
@@ -45,16 +31,6 @@
45
31
  has the status code specified. It's also possible to register an error
46
32
  page for a range of status codes: "error(500..599)".
47
33
 
48
- * Sinatra's testing support is no longer dependent on Test::Unit. Requiring
49
- 'sinatra/test' adds the Sinatra::Test module and Sinatra::TestHarness
50
- class, which can be used with any test framework. The 'sinatra/test/unit',
51
- 'sinatra/test/spec', 'sinatra/test/rspec', or 'sinatra/test/bacon' files
52
- can be required to setup a framework-specific testing environment. See the
53
- README for more information.
54
-
55
- * Added support for Bacon (test framework). The 'sinatra/test/bacon' file
56
- can be required to setup Sinatra test helpers on Bacon::Context.
57
-
58
34
  * Deprecated "set_option" and "set_options"; use "set" instead.
59
35
 
60
36
  * Deprecated the "env" option ("options.env"); use "environment" instead.
@@ -79,10 +55,6 @@
79
55
  treated as internal server errors and result in a 500 response
80
56
  status.
81
57
 
82
- * Deprecated the "get_it", "post_it", "put_it", "delete_it", and "head_it"
83
- test helper methods. Use "get", "post", "put", "delete", and "head",
84
- respectively, instead.
85
-
86
58
  * Removed Event and EventContext classes. Applications are defined in a
87
59
  subclass of Sinatra::Base; each request is processed within an
88
60
  instance.
data/README.rdoc CHANGED
@@ -1,7 +1,9 @@
1
1
  = Sinatra
2
2
 
3
3
  Sinatra is a DSL for quickly creating web-applications in Ruby with minimal
4
- effort:
4
+ effort.
5
+
6
+ == Sample App
5
7
 
6
8
  # myapp.rb
7
9
  require 'rubygems'
@@ -30,6 +32,10 @@ Run with <tt>ruby myapp.rb</tt> and view at <tt>http://localhost:4567</tt>
30
32
  .. annihilate something ..
31
33
  end
32
34
 
35
+ head '/' do
36
+
37
+ end
38
+
33
39
  == Routes
34
40
 
35
41
  Routes are matched based on the order of declaration. The first route that
@@ -41,17 +47,14 @@ Basic routes:
41
47
  ...
42
48
  end
43
49
 
44
- Route patterns may include named parameters, accessible via the
45
- <tt>params</tt> hash:
50
+ Named parameters:
46
51
 
47
52
  get '/:name' do
48
53
  # matches "GET /foo" and "GET /bar"
49
54
  # params[:name] is 'foo' or 'bar'
50
- "Hello #{params[:name]}!"
51
55
  end
52
56
 
53
- Route patterns may also include splat (or wildcard) parameters, accessible
54
- via the <tt>params[:splat]</tt> array.
57
+ Splat parameters:
55
58
 
56
59
  get '/say/*/to/*' do
57
60
  # matches /say/hello/to/world
@@ -63,13 +66,7 @@ via the <tt>params[:splat]</tt> array.
63
66
  params[:splat] # => ["path/to/file", "xml"]
64
67
  end
65
68
 
66
- Route matching with Regular Expressions:
67
-
68
- get %r{/hello/([\w]+)} do
69
- "Hello, #{params[:captures].first}!"
70
- end
71
-
72
- Routes may include a variety of matching conditions, such as the user agent:
69
+ User agent matching:
73
70
 
74
71
  get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
75
72
  "You're using Songbird version #{params[:agent][0]}"
@@ -81,29 +78,33 @@ Routes may include a variety of matching conditions, such as the user agent:
81
78
 
82
79
  == Static Files
83
80
 
84
- Static files are served from the <tt>./public</tt> directory. You can specify
85
- a different location by setting the <tt>:public</tt> option:
81
+ Put all of your static content in the ./public directory
82
+
83
+ root
84
+ \ public
85
+
86
+ To use a different static directory:
86
87
 
87
88
  set :public, File.dirname(__FILE__) + '/static'
88
89
 
89
- == Views / Templates
90
+ == Views
91
+
92
+ Views are searched for in a ./views directory in the same location as
93
+ your main application.
90
94
 
91
- Templates are assumed to be located directly under a <tt>./views</tt>
92
- directory. To use a different views directory:
95
+ To use a different views directory:
93
96
 
94
97
  set :views, File.dirname(__FILE__) + '/templates'
95
98
 
96
99
  === Haml Templates
97
100
 
98
- The haml gem/library is required to render HAML templates:
99
-
100
101
  get '/' do
101
102
  haml :index
102
103
  end
103
104
 
104
105
  Renders <tt>./views/index.haml</tt>.
105
106
 
106
- === Erb Templates
107
+ === Erb
107
108
 
108
109
  get '/' do
109
110
  erb :index
@@ -111,20 +112,11 @@ Renders <tt>./views/index.haml</tt>.
111
112
 
112
113
  Renders <tt>./views/index.erb</tt>
113
114
 
114
- === Builder Templates
115
+ === Builder
115
116
 
116
- The builder gem/library is required to render builder templates:
117
+ See Sinatra::Builder
117
118
 
118
- get '/' do
119
- content_type 'application/xml', :charset => 'utf-8'
120
- builder :index
121
- end
122
-
123
- Renders <tt>./views/index.builder</tt>.
124
-
125
- === Sass Templates
126
-
127
- The sass gem/library is required to render Sass templates:
119
+ === Sass
128
120
 
129
121
  get '/stylesheet.css' do
130
122
  content_type 'text/css', :charset => 'utf-8'
@@ -143,8 +135,9 @@ Renders the inlined template string.
143
135
 
144
136
  === Accessing Variables
145
137
 
146
- Templates are evaluated within the same context as the route blocks. Instance
147
- variables set in route blocks are available in templates:
138
+ Templates are evaluated within the Sinatra::EventContext instance
139
+ used to evaluate event blocks. Instance variables set in event
140
+ blocks can be accessed direcly in views:
148
141
 
149
142
  get '/:id' do
150
143
  @foo = Foo.find(params[:id])
@@ -165,32 +158,27 @@ other templates.
165
158
 
166
159
  Templates may be defined at the end of the source file:
167
160
 
168
- require 'rubygems'
169
- require 'sinatra'
170
-
171
161
  get '/' do
172
162
  haml :index
173
163
  end
174
164
 
165
+ use_in_file_templates!
166
+
175
167
  __END__
176
168
 
177
169
  @@ layout
178
- %html
179
- = yield
170
+ X
171
+ = yield
172
+ X
180
173
 
181
174
  @@ index
182
175
  %div.title Hello world!!!!!
183
176
 
184
- NOTE: Sinatra will automaticly load any in-file-templates in the
185
- source file that first required sinatra. If you have in-file-templates
186
- in another source file you will need to explicitly call
187
- +use_in_file_templates! on main in that file.
188
-
189
177
  It's also possible to define named templates using the top-level template
190
178
  method:
191
179
 
192
180
  template :layout do
193
- "%html\n =yield\n"
181
+ "X\n=yield\nX"
194
182
  end
195
183
 
196
184
  template :index do
@@ -201,17 +189,9 @@ method:
201
189
  haml :index
202
190
  end
203
191
 
204
- If a template named "layout" exists, it will be used each time a template
205
- is rendered. You can disable layouts by passing <tt>:layout => false</tt>.
206
-
207
- get '/' do
208
- haml :index, :layout => !request.xhr?
209
- end
210
-
211
192
  == Helpers
212
193
 
213
- Use the top-level <tt>helpers</tt> method to define helper methods for use in
214
- route blocks and templates:
194
+ The top-level <tt>helpers</tt> method
215
195
 
216
196
  helpers do
217
197
  def bar(name)
@@ -225,9 +205,7 @@ route blocks and templates:
225
205
 
226
206
  == Filters
227
207
 
228
- Before filters are evaluated before each request within the context of the
229
- request and can modify the request and response. Instance variables set in
230
- filters are accessible by routes and templates.
208
+ Before filters are evaluated in request context before routing is performed:
231
209
 
232
210
  before do
233
211
  @note = 'Hi!'
@@ -239,75 +217,64 @@ filters are accessible by routes and templates.
239
217
  params[:splat] #=> 'bar/baz'
240
218
  end
241
219
 
242
- == Halting
220
+ Before filters can modify the request and response; instance variables are
221
+ available to routes.
243
222
 
244
- To immediately stop a request during a before filter or route use:
223
+ == Halt!
245
224
 
246
- halt
225
+ To immediately stop a request during a before filter or event use:
247
226
 
248
- You can also specify a body when halting ...
227
+ throw :halt
249
228
 
250
- halt 'this will be the body'
229
+ Set the body to a simple string
251
230
 
252
- Set the status and body ...
231
+ throw :halt, 'this will be the body'
253
232
 
254
- halt 401, 'go away!'
233
+ Set status then the body
255
234
 
256
- == Passing
235
+ throw :halt, [401, 'go away!']
257
236
 
258
- A route can punt processing to the next matching route using the <tt>pass</tt>
259
- statement:
237
+ Run a proc inside the Sinatra::EventContext instance and set the body to the
238
+ result
260
239
 
261
- get '/guess/:who' do
262
- pass unless params[:who] == 'Frank'
263
- "You got me!"
264
- end
265
-
266
- get '/guess/*' do
267
- "You missed!"
268
- end
269
-
270
- The route block is immediately exited and control continues with the next
271
- matching route. If no matching route is found, a 404 is returned.
240
+ throw :halt, lambda { puts 'In a proc!'; 'I just wrote to $stdout!' }
272
241
 
273
242
  == Configuration and Reloading
274
243
 
275
244
  Sinatra supports multiple environments and reloading. Reloading happens
276
- before each request when running under the <tt>:development</tt>
277
- environment. Wrap your configurations (e.g., database connections, constants,
278
- etc.) in <tt>configure</tt> blocks to protect them from reloading or to
279
- target specific environments.
245
+ before every request when running under the :development environment. Wrap
246
+ your configurations in <tt>configure</tt> (i.e. Database connections, Constants,
247
+ etc.) to protect them from reloading or to target specific environments.
280
248
 
281
- Run once, at startup, in any environment:
249
+ All environments:
282
250
 
283
251
  configure do
284
252
  ...
285
253
  end
286
254
 
287
- Run only when the environment (RACK_ENV environment variable) is set to
288
- <tt>:production</tt>.
255
+ Production:
289
256
 
290
257
  configure :production do
291
258
  ...
292
259
  end
293
260
 
294
- Run when the environment (RACK_ENV environment variable) is set to
295
- either <tt>:production</tt> or <tt>:test</tt>.
261
+ Two at a time:
296
262
 
297
263
  configure :production, :test do
298
264
  ...
299
265
  end
300
266
 
267
+ This is also really nifty for error handling.
268
+
301
269
  == Error handling
302
270
 
303
- Error handlers run within the same context as routes and before filters, which
304
- means you get all the goodies it has to offer, like <tt>haml</tt>, <tt>erb</tt>,
305
- <tt>halt</tt>, etc.
271
+ Error handlers run inside the current Sinatra::EventContext instance, which
272
+ means you get all the goodies it has to offer (i.e. haml, erb, throw :halt,
273
+ etc.)
306
274
 
307
275
  === Not Found
308
276
 
309
- When a <tt>Sinatra::NotFound</tt> exception is raised, or the response's status
310
- code is 404, the <tt>not_found</tt> handler is invoked:
277
+ When Sinatra::NotFound is raised, the not_found handler is invoked:
311
278
 
312
279
  not_found do
313
280
  'This is nowhere to be found'
@@ -315,12 +282,14 @@ code is 404, the <tt>not_found</tt> handler is invoked:
315
282
 
316
283
  === Error
317
284
 
318
- The +error+ handler is invoked any time an exception is raised from a route
319
- block or before filter. The exception object can be obtained from the
320
- 'sinatra.error' Rack variable:
285
+ By default, the +error+ handler is invoked on Sinatra::ServerError or when
286
+ an unknown error occurs.
287
+
288
+ The exception can be obtained from the 'sinatra.error' variable in
289
+ request.env.
321
290
 
322
291
  error do
323
- 'Sorry there was a nasty error - ' + env['sinatra.error'].name
292
+ 'Sorry there was a nasty error - ' + request.env['sinatra.error'].name
324
293
  end
325
294
 
326
295
  Custom errors:
@@ -340,12 +309,12 @@ You get this:
340
309
  So what happened was... something bad
341
310
 
342
311
  Sinatra installs special not_found and error handlers when running under
343
- the development environment.
312
+ the development.
344
313
 
345
314
  == Mime types
346
315
 
347
- When using <tt>send_file</tt> or static files you may have mime types Sinatra
348
- doesn't understand. Use +mime+ to register them by file extension:
316
+ When using send_file or static files you may have mime types Sinatra doesn't
317
+ understand. Use +mime+ in those cases.
349
318
 
350
319
  mime :foo, 'text/foo'
351
320
 
@@ -386,61 +355,59 @@ typically don't have to +use+ them explicitly.
386
355
 
387
356
  == Testing
388
357
 
389
- The Sinatra::Test module includes a variety of helper methods for testing
390
- your Sinatra app. Sinatra includes support for Test::Unit, test-spec, RSpec,
391
- and Bacon through separate source files.
392
-
393
- === Test::Unit
358
+ === Test/Unit
394
359
 
360
+ require 'rubygems'
395
361
  require 'sinatra'
396
362
  require 'sinatra/test/unit'
397
363
  require 'my_sinatra_app'
398
364
 
399
365
  class MyAppTest < Test::Unit::TestCase
366
+
400
367
  def test_my_default
401
- get '/'
368
+ get_it '/'
402
369
  assert_equal 'My Default Page!', @response.body
403
370
  end
404
371
 
405
372
  def test_with_agent
406
- get '/', :agent => 'Songbird'
373
+ get_it '/', :agent => 'Songbird'
407
374
  assert_equal 'You're in Songbird!', @response.body
408
375
  end
409
376
 
410
377
  ...
411
- end
412
378
 
413
- === Test::Spec
379
+ end
414
380
 
415
- Install the test-spec gem and require <tt>'sinatra/test/spec'</tt> before
416
- your app:
381
+ === Test/Spec
417
382
 
383
+ require 'rubygems'
418
384
  require 'sinatra'
419
385
  require 'sinatra/test/spec'
420
386
  require 'my_sinatra_app'
421
387
 
422
388
  describe 'My app' do
389
+
423
390
  it "should show a default page" do
424
- get '/'
391
+ get_it '/'
425
392
  should.be.ok
426
393
  body.should.equal 'My Default Page!'
427
394
  end
428
395
 
429
396
  ...
397
+
430
398
  end
431
399
 
432
400
  === RSpec
433
401
 
434
- Install the rspec gem and require <tt>'sinatra/test/rspec'</tt> before
435
- your app:
436
-
402
+ require 'rubygems'
403
+ require 'spec'
437
404
  require 'sinatra'
438
405
  require 'sinatra/test/rspec'
439
406
  require 'my_sinatra_app'
440
407
 
441
408
  describe 'My app' do
442
409
  it 'should show a default page' do
443
- get '/'
410
+ get_it '/'
444
411
  @response.should be_ok
445
412
  @response.body.should == 'My Default Page!'
446
413
  end
@@ -449,35 +416,20 @@ your app:
449
416
 
450
417
  end
451
418
 
452
- === Bacon
453
-
454
- require 'sinatra'
455
- require 'sinatra/test/bacon'
456
- require 'my_sinatra_app'
457
-
458
- describe 'My app' do
459
- it 'should be ok' do
460
- get '/'
461
- should.be.ok
462
- body.should == 'Im OK'
463
- end
464
- end
465
-
466
- See Sinatra::Test for more information on +get+, +post+, +put+, and
467
- friends.
419
+ See Sinatra::Test::Methods for more information on +get_it+, +post_it+,
420
+ +put_it+, and friends.
468
421
 
469
422
  == Command line
470
423
 
471
424
  Sinatra applications can be run directly:
472
425
 
473
- ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-s HANDLER]
426
+ ruby myapp.rb [-h] [-x] [-p PORT] [-e ENVIRONMENT]
474
427
 
475
428
  Options are:
476
429
 
477
430
  -h # help
478
431
  -p # set the port (default is 4567)
479
432
  -e # set the environment (default is development)
480
- -s # specify rack server/handler (default is thin)
481
433
  -x # turn on the mutex lock (default is off)
482
434
 
483
435
  == Contributing
@@ -510,7 +462,7 @@ screencasts about Git, which you can find here: http://www.gitcasts.com/
510
462
 
511
463
  at the top of your sinatra_app.rb file:
512
464
 
513
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
465
+ $:.unshift File.dirname(__FILE__) + '/sinatra/lib'
514
466
  require 'sinatra'
515
467
 
516
468
  get '/about' do
@@ -1,6 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
3
  context "Simple Events" do
4
+
4
5
  def simple_request_hash(method, path)
5
6
  Rack::Request.new({
6
7
  'REQUEST_METHOD' => method.to_s.upcase,
@@ -13,16 +14,16 @@ context "Simple Events" do
13
14
 
14
15
  def invoke_simple(path, request_path, &b)
15
16
  params = nil
16
- get path do
17
- params = self.params
18
- b.call if b
19
- end
17
+ mock_app {
18
+ get path do
19
+ params = self.params
20
+ b.call if b
21
+ end
22
+ }
20
23
  get_it request_path
21
24
  MockResult.new(b, params)
22
25
  end
23
26
 
24
- setup { Sinatra.application = nil }
25
-
26
27
  specify "return last value" do
27
28
  block = Proc.new { 'Simple' }
28
29
  result = invoke_simple('/', '/', &block)
@@ -37,7 +38,6 @@ context "Simple Events" do
37
38
  result.params.should.equal "foo" => 'a', "bar" => 'b'
38
39
 
39
40
  # unscapes
40
- Sinatra.application = nil
41
41
  result = invoke_simple('/:foo/:bar', '/a/blake%20mizerany')
42
42
  result.should.not.be.nil
43
43
  result.params.should.equal "foo" => 'a', "bar" => 'blake mizerany'
@@ -48,17 +48,14 @@ context "Simple Events" do
48
48
  result.should.not.be.nil
49
49
  result.params.should.equal "foo" => 'a', "bar" => 'b'
50
50
 
51
- Sinatra.application = nil
52
51
  result = invoke_simple('/?:foo?/?:bar?', '/a/')
53
52
  result.should.not.be.nil
54
53
  result.params.should.equal "foo" => 'a', "bar" => nil
55
54
 
56
- Sinatra.application = nil
57
55
  result = invoke_simple('/?:foo?/?:bar?', '/a')
58
56
  result.should.not.be.nil
59
57
  result.params.should.equal "foo" => 'a', "bar" => nil
60
58
 
61
- Sinatra.application = nil
62
59
  result = invoke_simple('/:foo?/?:bar?', '/')
63
60
  result.should.not.be.nil
64
61
  result.params.should.equal "foo" => nil, "bar" => nil
data/compat/helper.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'mocha'
3
3
 
4
- # disable warnings in compat specs.
5
- $VERBOSE = nil
6
-
7
4
  $:.unshift File.dirname(File.dirname(__FILE__)) + "/lib"
8
5
 
9
6
  ENV['RACK_ENV'] ||= 'test'
@@ -13,18 +10,9 @@ require 'sinatra/test'
13
10
  require 'sinatra/test/unit'
14
11
  require 'sinatra/test/spec'
15
12
 
16
- module Sinatra::Test
17
- # we need to remove the new test helper methods since they conflict with
18
- # the top-level methods of the same name.
19
- %w(get head post put delete).each do |verb|
20
- remove_method verb
21
- end
22
- include Sinatra::Delegator
23
- end
24
-
25
13
  class Test::Unit::TestCase
26
- include Sinatra::Test
27
14
  def setup
28
15
  @app = lambda { |env| Sinatra::Application.call(env) }
29
16
  end
17
+ include Sinatra::Test
30
18
  end