sinatra-bundles 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. data/Rakefile +2 -1
  2. data/VERSION +1 -1
  3. data/lib/sinatra/bundles/bundle.rb +36 -0
  4. data/lib/sinatra/bundles/helpers.rb +22 -0
  5. data/lib/sinatra/bundles/javascript_bundle.rb +37 -0
  6. data/lib/sinatra/bundles/stylesheet_bundle.rb +36 -0
  7. data/lib/sinatra/bundles.rb +4 -114
  8. data/sinatra-bundles.gemspec +11 -58
  9. data/spec/app.rb +1 -1
  10. data/spec/production_app.rb +1 -1
  11. data/spec/public/javascripts/eval.js +5 -0
  12. data/spec/sinatra-bundles_spec.rb +10 -1
  13. data/spec/spec_helper.rb +5 -6
  14. metadata +17 -57
  15. data/vendor/cache/sinatra-0.10.1.gem +0 -0
  16. data/vendor/gems/sinatra-0.10.1/AUTHORS +0 -43
  17. data/vendor/gems/sinatra-0.10.1/CHANGES +0 -467
  18. data/vendor/gems/sinatra-0.10.1/LICENSE +0 -22
  19. data/vendor/gems/sinatra-0.10.1/README.jp.rdoc +0 -552
  20. data/vendor/gems/sinatra-0.10.1/README.rdoc +0 -622
  21. data/vendor/gems/sinatra-0.10.1/Rakefile +0 -129
  22. data/vendor/gems/sinatra-0.10.1/lib/sinatra/base.rb +0 -1143
  23. data/vendor/gems/sinatra-0.10.1/lib/sinatra/images/404.png +0 -0
  24. data/vendor/gems/sinatra-0.10.1/lib/sinatra/images/500.png +0 -0
  25. data/vendor/gems/sinatra-0.10.1/lib/sinatra/main.rb +0 -28
  26. data/vendor/gems/sinatra-0.10.1/lib/sinatra/showexceptions.rb +0 -303
  27. data/vendor/gems/sinatra-0.10.1/lib/sinatra/tilt.rb +0 -509
  28. data/vendor/gems/sinatra-0.10.1/lib/sinatra.rb +0 -7
  29. data/vendor/gems/sinatra-0.10.1/sinatra.gemspec +0 -86
  30. data/vendor/gems/sinatra-0.10.1/test/base_test.rb +0 -160
  31. data/vendor/gems/sinatra-0.10.1/test/builder_test.rb +0 -65
  32. data/vendor/gems/sinatra-0.10.1/test/contest.rb +0 -64
  33. data/vendor/gems/sinatra-0.10.1/test/erb_test.rb +0 -81
  34. data/vendor/gems/sinatra-0.10.1/test/erubis_test.rb +0 -82
  35. data/vendor/gems/sinatra-0.10.1/test/extensions_test.rb +0 -100
  36. data/vendor/gems/sinatra-0.10.1/test/filter_test.rb +0 -195
  37. data/vendor/gems/sinatra-0.10.1/test/haml_test.rb +0 -90
  38. data/vendor/gems/sinatra-0.10.1/test/helper.rb +0 -76
  39. data/vendor/gems/sinatra-0.10.1/test/helpers_test.rb +0 -573
  40. data/vendor/gems/sinatra-0.10.1/test/mapped_error_test.rb +0 -186
  41. data/vendor/gems/sinatra-0.10.1/test/middleware_test.rb +0 -68
  42. data/vendor/gems/sinatra-0.10.1/test/request_test.rb +0 -33
  43. data/vendor/gems/sinatra-0.10.1/test/response_test.rb +0 -42
  44. data/vendor/gems/sinatra-0.10.1/test/result_test.rb +0 -98
  45. data/vendor/gems/sinatra-0.10.1/test/route_added_hook_test.rb +0 -59
  46. data/vendor/gems/sinatra-0.10.1/test/routing_test.rb +0 -878
  47. data/vendor/gems/sinatra-0.10.1/test/sass_test.rb +0 -79
  48. data/vendor/gems/sinatra-0.10.1/test/server_test.rb +0 -47
  49. data/vendor/gems/sinatra-0.10.1/test/sinatra_test.rb +0 -13
  50. data/vendor/gems/sinatra-0.10.1/test/static_test.rb +0 -87
  51. data/vendor/gems/sinatra-0.10.1/test/templates_test.rb +0 -155
  52. data/vendor/gems/sinatra-0.10.1/test/views/error.builder +0 -3
  53. data/vendor/gems/sinatra-0.10.1/test/views/error.erb +0 -3
  54. data/vendor/gems/sinatra-0.10.1/test/views/error.erubis +0 -3
  55. data/vendor/gems/sinatra-0.10.1/test/views/error.haml +0 -3
  56. data/vendor/gems/sinatra-0.10.1/test/views/error.sass +0 -2
  57. data/vendor/gems/sinatra-0.10.1/test/views/foo/hello.test +0 -1
  58. data/vendor/gems/sinatra-0.10.1/test/views/hello.builder +0 -1
  59. data/vendor/gems/sinatra-0.10.1/test/views/hello.erb +0 -1
  60. data/vendor/gems/sinatra-0.10.1/test/views/hello.erubis +0 -1
  61. data/vendor/gems/sinatra-0.10.1/test/views/hello.haml +0 -1
  62. data/vendor/gems/sinatra-0.10.1/test/views/hello.sass +0 -2
  63. data/vendor/gems/sinatra-0.10.1/test/views/hello.test +0 -1
  64. data/vendor/gems/sinatra-0.10.1/test/views/layout2.builder +0 -3
  65. data/vendor/gems/sinatra-0.10.1/test/views/layout2.erb +0 -2
  66. data/vendor/gems/sinatra-0.10.1/test/views/layout2.erubis +0 -2
  67. data/vendor/gems/sinatra-0.10.1/test/views/layout2.haml +0 -2
  68. data/vendor/gems/sinatra-0.10.1/test/views/layout2.test +0 -1
  69. data/vendor/specifications/sinatra-0.10.1.gemspec +0 -40
@@ -1,622 +0,0 @@
1
- = Sinatra
2
-
3
- Sinatra is a DSL for quickly creating web applications in Ruby with minimal
4
- effort:
5
-
6
- # myapp.rb
7
- require 'rubygems'
8
- require 'sinatra'
9
- get '/' do
10
- 'Hello world!'
11
- end
12
-
13
- Install the gem and run with:
14
-
15
- sudo gem install sinatra
16
- ruby myapp.rb
17
-
18
- View at: http://localhost:4567
19
-
20
- == Routes
21
-
22
- In Sinatra, a route is an HTTP method paired with an URL matching pattern.
23
- Each route is associated with a block:
24
-
25
- get '/' do
26
- .. show something ..
27
- end
28
-
29
- post '/' do
30
- .. create something ..
31
- end
32
-
33
- put '/' do
34
- .. update something ..
35
- end
36
-
37
- delete '/' do
38
- .. annihilate something ..
39
- end
40
-
41
- Routes are matched in the order they are defined. The first route that
42
- matches the request is invoked.
43
-
44
- Route patterns may include named parameters, accessible via the
45
- <tt>params</tt> hash:
46
-
47
- get '/hello/:name' do
48
- # matches "GET /hello/foo" and "GET /hello/bar"
49
- # params[:name] is 'foo' or 'bar'
50
- "Hello #{params[:name]}!"
51
- end
52
-
53
- You can also access named parameters via block parameters:
54
-
55
- get '/hello/:name' do |n|
56
- "Hello #{n}!"
57
- end
58
-
59
- Route patterns may also include splat (or wildcard) parameters, accessible
60
- via the <tt>params[:splat]</tt> array.
61
-
62
- get '/say/*/to/*' do
63
- # matches /say/hello/to/world
64
- params[:splat] # => ["hello", "world"]
65
- end
66
-
67
- get '/download/*.*' do
68
- # matches /download/path/to/file.xml
69
- params[:splat] # => ["path/to/file", "xml"]
70
- end
71
-
72
- Route matching with Regular Expressions:
73
-
74
- get %r{/hello/([\w]+)} do
75
- "Hello, #{params[:captures].first}!"
76
- end
77
-
78
- Or with a block parameter:
79
-
80
- get %r{/hello/([\w]+)} do |c|
81
- "Hello, #{c}!"
82
- end
83
-
84
- Routes may include a variety of matching conditions, such as the user agent:
85
-
86
- get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
87
- "You're using Songbird version #{params[:agent][0]}"
88
- end
89
-
90
- get '/foo' do
91
- # Matches non-songbird browsers
92
- end
93
-
94
- == Static Files
95
-
96
- Static files are served from the <tt>./public</tt> directory. You can specify
97
- a different location by setting the <tt>:public</tt> option:
98
-
99
- set :public, File.dirname(__FILE__) + '/static'
100
-
101
- Note that the public directory name is not included in the URL. A file
102
- <tt>./public/css/style.css</tt> is made available as
103
- <tt>http://example.com/css/style.css</tt>.
104
-
105
- == Views / Templates
106
-
107
- Templates are assumed to be located directly under the <tt>./views</tt>
108
- directory. To use a different views directory:
109
-
110
- set :views, File.dirname(__FILE__) + '/templates'
111
-
112
- One important thing to remember is that you always have to reference
113
- templates with symbols, even if they're in a subdirectory (in this
114
- case use <tt>:'subdir/template'</tt>). Rendering methods will render
115
- any strings passed to them directly.
116
-
117
- === Haml Templates
118
-
119
- The haml gem/library is required to render HAML templates:
120
-
121
- ## You'll need to require haml in your app
122
- require 'haml'
123
-
124
- get '/' do
125
- haml :index
126
- end
127
-
128
- Renders <tt>./views/index.haml</tt>.
129
-
130
- {Haml's options}[http://haml.hamptoncatlin.com/docs/rdoc/classes/Haml.html]
131
- can be set globally through Sinatra's configurations,
132
- see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
133
- and overridden on an individual basis.
134
-
135
- set :haml, {:format => :html5 } # default Haml format is :xhtml
136
-
137
- get '/' do
138
- haml :index, :haml_options => {:format => :html4 } # overridden
139
- end
140
-
141
-
142
- === Erb Templates
143
-
144
- ## You'll need to require erb in your app
145
- require 'erb'
146
-
147
- get '/' do
148
- erb :index
149
- end
150
-
151
- Renders <tt>./views/index.erb</tt>
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
-
166
- === Builder Templates
167
-
168
- The builder gem/library is required to render builder templates:
169
-
170
- ## You'll need to require builder in your app
171
- require 'builder'
172
-
173
- get '/' do
174
- content_type 'application/xml', :charset => 'utf-8'
175
- builder :index
176
- end
177
-
178
- Renders <tt>./views/index.builder</tt>.
179
-
180
- === Sass Templates
181
-
182
- The sass gem/library is required to render Sass templates:
183
-
184
- ## You'll need to require haml or sass in your app
185
- require 'sass'
186
-
187
- get '/stylesheet.css' do
188
- content_type 'text/css', :charset => 'utf-8'
189
- sass :stylesheet
190
- end
191
-
192
- Renders <tt>./views/stylesheet.sass</tt>.
193
-
194
- {Sass' options}[http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html]
195
- can be set globally through Sinatra's configurations,
196
- see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
197
- and overridden on an individual basis.
198
-
199
- set :sass, {:style => :compact } # default Sass style is :nested
200
-
201
- get '/stylesheet.css' do
202
- content_type 'text/css', :charset => 'utf-8'
203
- sass :stylesheet, :style => :expanded # overridden
204
- end
205
-
206
- === Inline Templates
207
-
208
- get '/' do
209
- haml '%div.title Hello World'
210
- end
211
-
212
- Renders the inlined template string.
213
-
214
- === Accessing Variables in Templates
215
-
216
- Templates are evaluated within the same context as route handlers. Instance
217
- variables set in route handlers are direcly accessible by templates:
218
-
219
- get '/:id' do
220
- @foo = Foo.find(params[:id])
221
- haml '%h1= @foo.name'
222
- end
223
-
224
- Or, specify an explicit Hash of local variables:
225
-
226
- get '/:id' do
227
- foo = Foo.find(params[:id])
228
- haml '%h1= foo.name', :locals => { :foo => foo }
229
- end
230
-
231
- This is typically used when rendering templates as partials from within
232
- other templates.
233
-
234
- === Inline Templates
235
-
236
- Templates may be defined at the end of the source file:
237
-
238
- require 'rubygems'
239
- require 'sinatra'
240
-
241
- get '/' do
242
- haml :index
243
- end
244
-
245
- __END__
246
-
247
- @@ layout
248
- %html
249
- = yield
250
-
251
- @@ index
252
- %div.title Hello world!!!!!
253
-
254
- NOTE: Inline templates defined in the source file that requires sinatra
255
- are automatically loaded. Call `enable :inline_templates` explicitly if you
256
- have inline templates in other source files.
257
-
258
- === Named Templates
259
-
260
- Templates may also be defined using the top-level <tt>template</tt> method:
261
-
262
- template :layout do
263
- "%html\n =yield\n"
264
- end
265
-
266
- template :index do
267
- '%div.title Hello World!'
268
- end
269
-
270
- get '/' do
271
- haml :index
272
- end
273
-
274
- If a template named "layout" exists, it will be used each time a template
275
- is rendered. You can disable layouts by passing <tt>:layout => false</tt>.
276
-
277
- get '/' do
278
- haml :index, :layout => !request.xhr?
279
- end
280
-
281
- == Helpers
282
-
283
- Use the top-level <tt>helpers</tt> method to define helper methods for use in
284
- route handlers and templates:
285
-
286
- helpers do
287
- def bar(name)
288
- "#{name}bar"
289
- end
290
- end
291
-
292
- get '/:name' do
293
- bar(params[:name])
294
- end
295
-
296
- == Filters
297
-
298
- Before filters are evaluated before each request within the context of the
299
- request and can modify the request and response. Instance variables set in
300
- filters are accessible by routes and templates:
301
-
302
- before do
303
- @note = 'Hi!'
304
- request.path_info = '/foo/bar/baz'
305
- end
306
-
307
- get '/foo/*' do
308
- @note #=> 'Hi!'
309
- params[:splat] #=> 'bar/baz'
310
- end
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
-
320
- == Halting
321
-
322
- To immediately stop a request within a filter or route use:
323
-
324
- halt
325
-
326
- You can also specify the status when halting ...
327
-
328
- halt 410
329
-
330
- Or the body ...
331
-
332
- halt 'this will be the body'
333
-
334
- Or both ...
335
-
336
- halt 401, 'go away!'
337
-
338
- With headers ...
339
-
340
- halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
341
-
342
- == Passing
343
-
344
- A route can punt processing to the next matching route using <tt>pass</tt>:
345
-
346
- get '/guess/:who' do
347
- pass unless params[:who] == 'Frank'
348
- 'You got me!'
349
- end
350
-
351
- get '/guess/*' do
352
- 'You missed!'
353
- end
354
-
355
- The route block is immediately exited and control continues with the next
356
- matching route. If no matching route is found, a 404 is returned.
357
-
358
- == Configuration
359
-
360
- Run once, at startup, in any environment:
361
-
362
- configure do
363
- ...
364
- end
365
-
366
- Run only when the environment (RACK_ENV environment variable) is set to
367
- <tt>:production</tt>:
368
-
369
- configure :production do
370
- ...
371
- end
372
-
373
- Run when the environment is set to either <tt>:production</tt> or
374
- <tt>:test</tt>:
375
-
376
- configure :production, :test do
377
- ...
378
- end
379
-
380
- == Error handling
381
-
382
- Error handlers run within the same context as routes and before filters, which
383
- means you get all the goodies it has to offer, like <tt>haml</tt>, <tt>erb</tt>,
384
- <tt>halt</tt>, etc.
385
-
386
- === Not Found
387
-
388
- When a <tt>Sinatra::NotFound</tt> exception is raised, or the response's status
389
- code is 404, the <tt>not_found</tt> handler is invoked:
390
-
391
- not_found do
392
- 'This is nowhere to be found'
393
- end
394
-
395
- === Error
396
-
397
- The +error+ handler is invoked any time an exception is raised from a route
398
- block or a filter. The exception object can be obtained from the
399
- <tt>sinatra.error</tt> Rack variable:
400
-
401
- error do
402
- 'Sorry there was a nasty error - ' + env['sinatra.error'].name
403
- end
404
-
405
- Custom errors:
406
-
407
- error MyCustomError do
408
- 'So what happened was...' + request.env['sinatra.error'].message
409
- end
410
-
411
- Then, if this happens:
412
-
413
- get '/' do
414
- raise MyCustomError, 'something bad'
415
- end
416
-
417
- You get this:
418
-
419
- So what happened was... something bad
420
-
421
- Alternatively, you can install error handler for a status code:
422
-
423
- error 403 do
424
- 'Access forbidden'
425
- end
426
-
427
- get '/secret' do
428
- 403
429
- end
430
-
431
- Or a range:
432
-
433
- error 400..510 do
434
- 'Boom'
435
- end
436
-
437
- Sinatra installs special <tt>not_found</tt> and <tt>error</tt> handlers when
438
- running under the development environment.
439
-
440
- == Mime types
441
-
442
- When using <tt>send_file</tt> or static files you may have mime types Sinatra
443
- doesn't understand. Use +mime_type+ to register them by file extension:
444
-
445
- mime_type :foo, 'text/foo'
446
-
447
- You can also use it with the +content_type+ helper:
448
-
449
- content_type :foo
450
-
451
- == Rack Middleware
452
-
453
- Sinatra rides on Rack[http://rack.rubyforge.org/], a minimal standard
454
- interface for Ruby web frameworks. One of Rack's most interesting capabilities
455
- for application developers is support for "middleware" -- components that sit
456
- between the server and your application monitoring and/or manipulating the
457
- HTTP request/response to provide various types of common functionality.
458
-
459
- Sinatra makes building Rack middleware pipelines a cinch via a top-level
460
- +use+ method:
461
-
462
- require 'sinatra'
463
- require 'my_custom_middleware'
464
-
465
- use Rack::Lint
466
- use MyCustomMiddleware
467
-
468
- get '/hello' do
469
- 'Hello World'
470
- end
471
-
472
- The semantics of +use+ are identical to those defined for the
473
- Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html] DSL
474
- (most frequently used from rackup files). For example, the +use+ method
475
- accepts multiple/variable args as well as blocks:
476
-
477
- use Rack::Auth::Basic do |username, password|
478
- username == 'admin' && password == 'secret'
479
- end
480
-
481
- Rack is distributed with a variety of standard middleware for logging,
482
- debugging, URL routing, authentication, and session handling. Sinatra uses
483
- many of of these components automatically based on configuration so you
484
- typically don't have to +use+ them explicitly.
485
-
486
- == Testing
487
-
488
- Sinatra tests can be written using any Rack-based testing library
489
- or framework. {Rack::Test}[http://gitrdoc.com/brynary/rack-test] is
490
- recommended:
491
-
492
- require 'my_sinatra_app'
493
- require 'rack/test'
494
-
495
- class MyAppTest < Test::Unit::TestCase
496
- include Rack::Test::Methods
497
-
498
- def app
499
- Sinatra::Application
500
- end
501
-
502
- def test_my_default
503
- get '/'
504
- assert_equal 'Hello World!', last_response.body
505
- end
506
-
507
- def test_with_params
508
- get '/meet', :name => 'Frank'
509
- assert_equal 'Hello Frank!', last_response.body
510
- end
511
-
512
- def test_with_rack_env
513
- get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
514
- assert_equal "You're using Songbird!", last_response.body
515
- end
516
- end
517
-
518
- NOTE: The built-in Sinatra::Test module and Sinatra::TestHarness class
519
- are deprecated as of the 0.9.2 release.
520
-
521
- == Sinatra::Base - Middleware, Libraries, and Modular Apps
522
-
523
- Defining your app at the top-level works well for micro-apps but has
524
- considerable drawbacks when building reuseable components such as Rack
525
- middleware, Rails metal, simple libraries with a server component, or
526
- even Sinatra extensions. The top-level DSL pollutes the Object namespace
527
- and assumes a micro-app style configuration (e.g., a single application
528
- file, ./public and ./views directories, logging, exception detail page,
529
- etc.). That's where Sinatra::Base comes into play:
530
-
531
- require 'sinatra/base'
532
-
533
- class MyApp < Sinatra::Base
534
- set :sessions, true
535
- set :foo, 'bar'
536
-
537
- get '/' do
538
- 'Hello world!'
539
- end
540
- end
541
-
542
- The MyApp class is an independent Rack component that can act as
543
- Rack middleware, a Rack application, or Rails metal. You can +use+ or
544
- +run+ this class from a rackup +config.ru+ file; or, control a server
545
- component shipped as a library:
546
-
547
- MyApp.run! :host => 'localhost', :port => 9090
548
-
549
- The methods available to Sinatra::Base subclasses are exactly as those
550
- available via the top-level DSL. Most top-level apps can be converted to
551
- Sinatra::Base components with two modifications:
552
-
553
- * Your file should require +sinatra/base+ instead of +sinatra+;
554
- otherwise, all of Sinatra's DSL methods are imported into the main
555
- namespace.
556
- * Put your app's routes, error handlers, filters, and options in a subclass
557
- of Sinatra::Base.
558
-
559
- +Sinatra::Base+ is a blank slate. Most options are disabled by default,
560
- including the built-in server. See {Options and Configuration}[http://sinatra.github.com/configuration.html]
561
- for details on available options and their behavior.
562
-
563
- SIDEBAR: Sinatra's top-level DSL is implemented using a simple delegation
564
- system. The +Sinatra::Application+ class -- a special subclass of
565
- Sinatra::Base -- receives all :get, :put, :post, :delete, :before,
566
- :error, :not_found, :configure, and :set messages sent to the
567
- top-level. Have a look at the code for yourself: here's the
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].
570
-
571
- == Command line
572
-
573
- Sinatra applications can be run directly:
574
-
575
- ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-h HOST] [-s HANDLER]
576
-
577
- Options are:
578
-
579
- -h # help
580
- -p # set the port (default is 4567)
581
- -h # set the host (default is 0.0.0.0)
582
- -e # set the environment (default is development)
583
- -s # specify rack server/handler (default is thin)
584
- -x # turn on the mutex lock (default is off)
585
-
586
- == The Bleeding Edge
587
-
588
- If you would like to use Sinatra's latest bleeding code, create a local
589
- clone and run your app with the <tt>sinatra/lib</tt> directory on the
590
- <tt>LOAD_PATH</tt>:
591
-
592
- cd myapp
593
- git clone git://github.com/sinatra/sinatra.git
594
- ruby -Isinatra/lib myapp.rb
595
-
596
- Alternatively, you can add the <tt>sinatra/lib</tt> directory to the
597
- <tt>LOAD_PATH</tt> in your application:
598
-
599
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
600
- require 'rubygems'
601
- require 'sinatra'
602
-
603
- get '/about' do
604
- "I'm running version " + Sinatra::VERSION
605
- end
606
-
607
- To update the Sinatra sources in the future:
608
-
609
- cd myproject/sinatra
610
- git pull
611
-
612
- == More
613
-
614
- * {Project Website}[http://sinatra.github.com/] - Additional documentation,
615
- news, and links to other resources.
616
- * {Contributing}[http://sinatra.github.com/contributing.html] - Find a bug? Need
617
- help? Have a patch?
618
- * {Lighthouse}[http://sinatra.lighthouseapp.com] - Issue tracking and release
619
- planning.
620
- * {Twitter}[http://twitter.com/sinatra]
621
- * {Mailing List}[http://groups.google.com/group/sinatrarb]
622
- * {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net