hobby 0.0.6 → 0.0.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 866906249cfb187bc16dad3e74ddb38aac06fa32
4
- data.tar.gz: 7f654e325e34a802370869c4713260df9f169756
3
+ metadata.gz: c943dce2451a4154082cfe2d8fc823273b28c627
4
+ data.tar.gz: 78ab9a63570bea6044c18307c8bb2cb7b355b935
5
5
  SHA512:
6
- metadata.gz: 5aafd05f85c81e0d8af6ce2bbf9cfd9d0da3fd4bf7ff70ea7d1df7bc837eab50824c6a2222ff393974d8fb09b850e9b5fffa25c6c7b91796d6313fe542a7165e
7
- data.tar.gz: 5cf2deda1c0d46698af9a9607cd9003ae6c98dffc4abc68c0a3b3799f6eb633b8edb0f02015a715a5e1674a428c8e88a0d24619676bcf946fd807c0651a2bf7b
6
+ metadata.gz: 12fc9f283cd851d77de6132caa8ac74401854547b2f0f2639726857327dcf01da99fc8a7e962c924a0f1a644645576c94f51544e596eac98bf280f0a6ce11f9c
7
+ data.tar.gz: 3bb0e84f2b8195a51dbbe61bb37d7caea77cfda4dcf02ccea9812a7c037d0ce2d43ee13bf0e4fc12638cb3e5512f8aa24a0ac330460907da70878107b8ddc339
data/Gemfile CHANGED
@@ -1,6 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'devtools'
3
+ gem 'devtools', github: 'mbj/devtools'
4
+ gem 'mutant', github: 'mbj/mutant'
4
5
  gem 'minitest'
5
6
  gem 'minitest-power_assert'
6
7
  gem 'rack-test'
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'hobby'
7
- spec.version = '0.0.6'
7
+ spec.version = '0.0.7'
8
8
  spec.authors = ['Anatoly Chernow']
9
9
  spec.email = ['chertoly@gmail.com']
10
10
  spec.summary = %q{A minimal DSL over rack}
@@ -64,4 +64,8 @@ module Hobby
64
64
  def my
65
65
  env.fetch :path_params, {}
66
66
  end
67
+
68
+ def halt
69
+ throw :halt, response
70
+ end
67
71
  end
@@ -0,0 +1,360 @@
1
+ [[installation]]
2
+ == Installation
3
+
4
+ Add this line to your application's Gemfile:
5
+
6
+ [source,ruby]
7
+ ----
8
+ gem 'hobby'
9
+ # or this if you want to use hobby master
10
+ # gem 'hobby', github: 'ch1c0t/hobby'
11
+ ----
12
+
13
+ And then execute:
14
+
15
+ [source,bash]
16
+ ----
17
+ $ bundle
18
+ ----
19
+
20
+ Or install it yourself as:
21
+
22
+ [source,bash]
23
+ ----
24
+ $ gem install hobby
25
+ ----
26
+
27
+ [[introduction]]
28
+ == Introduction
29
+
30
+ Hobby features a Sinatra-like DSL, but in contrast to Sinatra,
31
+ Hobby applications behave like usual Ruby classes.
32
+
33
+ To create a Hobby application, you create a class and include `Hobby` in it.
34
+ For example:
35
+
36
+ [source,ruby]
37
+ ----
38
+ require 'hobby'
39
+
40
+ class C
41
+ include Hobby
42
+
43
+ get("/hello") {
44
+ "Hello, world."
45
+ }
46
+ end
47
+ ----
48
+
49
+ Then, you can create an instance of `C` with
50
+
51
+ [source,ruby]
52
+ ----
53
+ C.new
54
+ ----
55
+
56
+ which will return a Rack application(an object which complies to
57
+ http://rubydoc.info/github/rack/rack/master/file/SPEC[Rack SPEC]).
58
+
59
+ Because a Hobby application is just a Ruby class,
60
+ you can do with it pretty much anything
61
+ you would expect to be able to do with a Ruby class.
62
+
63
+ [[using-initialize]]
64
+ === Using #initialize
65
+
66
+ You can set some state in `#initialize` and then use it in the route's action:
67
+
68
+ [source,ruby]
69
+ ----
70
+ class C
71
+ include Hobby
72
+
73
+ def initialize name
74
+ @name = name
75
+ end
76
+
77
+ get("/hello") {
78
+ "Hello, #{@name}."
79
+ }
80
+ end
81
+ ----
82
+
83
+ [[using-intance-methods]]
84
+ === Using instance methods
85
+ [source,ruby]
86
+ ----
87
+ class C
88
+ include Hobby
89
+
90
+ def initialize name
91
+ @name = name
92
+ end
93
+
94
+ def name
95
+ @name.upcase
96
+ end
97
+
98
+ get("/hello") {
99
+ "Hello, #{name}."
100
+ }
101
+ end
102
+ ----
103
+
104
+ [[how-to-run]]
105
+ === How to run
106
+ To run an application, you can put it into `config.ru`:
107
+
108
+ [source,ruby]
109
+ ----
110
+ run C.new 'Hobby'
111
+ ----
112
+
113
+ and then use `rackup`:
114
+
115
+ [source,bash]
116
+ ----
117
+ $ rackup
118
+ ----
119
+
120
+ Or, if you are using Rails, you can mount it in `config/routes.rb` with:
121
+ [source,ruby]
122
+ ----
123
+ mount C.new('Hobby') => '/some_path'
124
+ ----
125
+
126
+ [[features]]
127
+ Features
128
+ ~~~~~~~~
129
+
130
+ * DSL inspired by http://www.sinatrarb.com/[Sinatra].
131
+ * https://github.com/luislavena/bench-micro[Speed].
132
+ * Extensible with standard ruby classes and modules, with no extra
133
+ logic. See https://github.com/ch1c0t/hobby-auth[hobby-auth] and
134
+ https://github.com/ch1c0t/hobby-json[hobby-json].
135
+ * Zero configuration.
136
+
137
+ [[routes]]
138
+ == Routes
139
+
140
+ For common HTTP verbs, Hobby provides the route definers(methods named accordingly):
141
+
142
+ [source,ruby]
143
+ ----
144
+ class App
145
+ include Hobby
146
+
147
+ get '/' do
148
+ # ...
149
+ end
150
+
151
+ post '/' do
152
+ # ...
153
+ end
154
+
155
+ put '/' do
156
+ # ...
157
+ end
158
+
159
+ patch '/' do
160
+ # ...
161
+ end
162
+
163
+ delete '/' do
164
+ # ...
165
+ end
166
+
167
+ options '/' do
168
+ # ...
169
+ end
170
+ end
171
+ ----
172
+
173
+ A definer should be called with a path(optional) and an action(passed as a block).
174
+
175
+ Calling a definer has a side effect of defining a route in the router.
176
+ When an incoming request matches a route,
177
+ the action is executed and a response is sent back to the client.
178
+ The return value of the action will be the `body` of the response.
179
+
180
+ If a path was omitted
181
+ [source,ruby]
182
+ ----
183
+ get do
184
+ 'The body returned to the HTTP client making the request.'
185
+ end
186
+ ----
187
+
188
+ the action is attached to the root route, like if
189
+ [source,ruby]
190
+ ----
191
+ get '/' do
192
+ 'The body returned to the HTTP client making the request.'
193
+ end
194
+ ----
195
+
196
+ were called.
197
+
198
+
199
+ [[default-methods]]
200
+ == Default methods
201
+
202
+ The following methods are predefined:
203
+
204
+ * `env`: a `Hash`, http://www.rubydoc.info/github/rack/rack/master/file/SPEC#The_Environment[a Rack environment].
205
+ * `request`: a http://www.rubydoc.info/gems/rack/Rack/Request[`Rack::Request`].
206
+ * `response`: a http://www.rubydoc.info/gems/rack/Rack/Response[`Rack::Response`].
207
+ * `my`: a `Hash` which stores route variables. See <<routes-with-variables>> for a usage example.
208
+ * `halt`: returns the `response` immediately. See <<halting>> for a usage example.
209
+
210
+ [[routes-with-variables]]
211
+ === Routes with variables
212
+
213
+ [source,ruby]
214
+ ----
215
+ class App
216
+ include Hobby
217
+ # matches both /hi/hobbit and /hi/patricio
218
+ get '/hi/:name' do
219
+ "Hello #{my[:name]}"
220
+ end
221
+ end
222
+ ----
223
+
224
+ [[halting]]
225
+ === Halting
226
+
227
+ [source,ruby]
228
+ ----
229
+ class App
230
+ include Hobby
231
+
232
+ use Rack::Session::Cookie, secret: SecureRandom.hex(64)
233
+
234
+ def session
235
+ env['rack.session']
236
+ end
237
+
238
+ get '/' do
239
+ response.status = 401
240
+ halt
241
+ 'This line is never going to be returned.'
242
+ end
243
+ end
244
+ ----
245
+
246
+ [[extensions]]
247
+ == Extensions
248
+
249
+ You can extend Hobby with usual modules:
250
+
251
+ [source,ruby]
252
+ ----
253
+ module MyExtension
254
+ def do_something
255
+ # do something
256
+ end
257
+ end
258
+
259
+ class App
260
+ include Hobby
261
+ include MyExtension
262
+
263
+ get '/' do
264
+ do_something
265
+ 'Hello World!'
266
+ end
267
+ end
268
+ ----
269
+
270
+ [[available-extensions]]
271
+ === Available extensions
272
+
273
+ * https://github.com/ch1c0t/hobby-json[hobby-json]: JSON requests and responses.
274
+ * https://github.com/ch1c0t/hobby-auth[hobby-auth]: User authorization.
275
+
276
+
277
+ [[using-rack-builder]]
278
+ == Using Rack::Builder
279
+
280
+ You can use `map` and `use` from http://www.rubydoc.info/gems/rack/Rack/Builder[Rack::Builder].
281
+
282
+ [[mapping-applications]]
283
+ === Mapping applications
284
+
285
+ You can mount any Rack application to a Hobby application with `map`.
286
+ Here is an example of mounting the application from <<using-initialize>>
287
+ to '/anatoly' and '/patricio' routes:
288
+
289
+ [source,ruby]
290
+ ----
291
+ class App
292
+ include Hobby
293
+
294
+ map('/anatoly') { run C.new 'Anatoly' }
295
+ map('/patricio') { run C.new 'Patricio' }
296
+
297
+ get '/' do
298
+ 'Mapping app.'
299
+ end
300
+ end
301
+ ----
302
+
303
+ [[using-middleware]]
304
+ === Using middleware
305
+
306
+ You can use any Rack middleware with `use`:
307
+
308
+ [source,ruby]
309
+ ----
310
+ class App
311
+ include Hobby
312
+
313
+ use Rack::Session::Cookie, secret: SecureRandom.hex(64)
314
+ use Rack::ShowExceptions
315
+
316
+ def session
317
+ env['rack.session']
318
+ end
319
+
320
+ get '/' do
321
+ session[:name] = 'username'
322
+ end
323
+ end
324
+ ----
325
+
326
+ == Custom components
327
+
328
+ Hobby was designed to be very modular.
329
+ Many components of an application can be customized or replaced.
330
+
331
+ [source,ruby]
332
+ ----
333
+ class App
334
+ include Hobby
335
+
336
+ self.builder = custom_builder
337
+ self.router = custom_router
338
+ self.request = custom_request
339
+ self.response = custom_response
340
+ end
341
+ ----
342
+
343
+ TODO: document the API which is expected from each of these components
344
+ and provide usage examples.
345
+
346
+ == Development
347
+
348
+ To run the specs:
349
+
350
+ [source,bash]
351
+ ----
352
+ bundle exec rspec
353
+ ----
354
+
355
+ To perform mutantion analysis:
356
+
357
+ [source,bash]
358
+ ----
359
+ bundle exec mutant --use rspec 'Hobby*'
360
+ ----
@@ -150,7 +150,7 @@ describe Hobby::App do
150
150
  end
151
151
  end
152
152
 
153
- describe Throw do
153
+ describe Halting do
154
154
  it do
155
155
  get '/'
156
156
  assert { last_response.status == 400 }
@@ -1,4 +1,5 @@
1
1
  get do
2
2
  response.status = 400
3
- throw :halt, response
3
+ halt
4
+ response.status = 200
4
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hobby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anatoly Chernow
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-27 00:00:00.000000000 Z
11
+ date: 2017-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -36,21 +36,21 @@ files:
36
36
  - CHANGELOG.md
37
37
  - Gemfile
38
38
  - LICENSE
39
- - README.md
40
39
  - Rakefile
41
40
  - hobby.gemspec
42
41
  - lib/hobby.rb
43
42
  - lib/hobby/router.rb
44
43
  - lib/hobby/router/route.rb
45
44
  - lib/hobby/router/routes.rb
45
+ - readme.adoc
46
46
  - spec/app_spec.rb
47
47
  - spec/apps/Decorator.rb
48
48
  - spec/apps/Env.rb
49
+ - spec/apps/Halting.rb
49
50
  - spec/apps/Main.rb
50
51
  - spec/apps/Map.rb
51
52
  - spec/apps/Nested.rb
52
53
  - spec/apps/OneRouteRouter.rb
53
- - spec/apps/Throw.rb
54
54
  - spec/apps/Use.rb
55
55
  - spec/apps/WithoutPath.rb
56
56
  - spec/helper.rb
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
76
  version: '0'
77
77
  requirements: []
78
78
  rubyforge_project:
79
- rubygems_version: 2.5.2
79
+ rubygems_version: 2.6.11
80
80
  signing_key:
81
81
  specification_version: 4
82
82
  summary: A minimal DSL over rack
@@ -84,11 +84,11 @@ test_files:
84
84
  - spec/app_spec.rb
85
85
  - spec/apps/Decorator.rb
86
86
  - spec/apps/Env.rb
87
+ - spec/apps/Halting.rb
87
88
  - spec/apps/Main.rb
88
89
  - spec/apps/Map.rb
89
90
  - spec/apps/Nested.rb
90
91
  - spec/apps/OneRouteRouter.rb
91
- - spec/apps/Throw.rb
92
92
  - spec/apps/Use.rb
93
93
  - spec/apps/WithoutPath.rb
94
94
  - spec/helper.rb
data/README.md DELETED
@@ -1,378 +0,0 @@
1
- # Hobbit [![Build Status](http://img.shields.io/travis/patriciomacadden/hobbit.svg)](https://travis-ci.org/patriciomacadden/hobbit) [![Code Climate](http://img.shields.io/codeclimate/github/patriciomacadden/hobbit.svg)](https://codeclimate.com/github/patriciomacadden/hobbit) [![Code Climate Coverage](http://img.shields.io/codeclimate/coverage/github/patriciomacadden/hobbit.svg)](https://codeclimate.com/github/patriciomacadden/hobbit) [![Dependency Status](http://img.shields.io/gemnasium/patriciomacadden/hobbit.svg)](https://gemnasium.com/patriciomacadden/hobbit) [![Gem Version](http://img.shields.io/gem/v/hobbit.svg)](http://badge.fury.io/rb/hobbit)
2
-
3
- A minimalistic microframework built on top of [Rack](http://rack.github.io/).
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- ```ruby
10
- gem 'hobbit'
11
- # or this if you want to use hobbit master
12
- # gem 'hobbit', github: 'patriciomacadden/hobbit'
13
- ```
14
-
15
- And then execute:
16
-
17
- ```bash
18
- $ bundle
19
- ```
20
-
21
- Or install it yourself as:
22
-
23
- ```bash
24
- $ gem install hobbit
25
- ```
26
-
27
- ## Features
28
-
29
- * DSL inspired by [Sinatra](http://www.sinatrarb.com/).
30
- * [Speed](https://github.com/luislavena/bench-micro).
31
- * Extensible with standard ruby classes and modules, with no extra logic. See
32
- [hobbit-contrib](https://github.com/patriciomacadden/hobbit-contrib).
33
- * Zero configuration.
34
-
35
- ## Philosophy
36
-
37
- * [Don't repeat yourself](http://en.wikipedia.org/wiki/Don't_repeat_yourself)
38
- * Encourages the understanding and use of [Rack](http://rack.github.io/) and
39
- its extensions instead of providing such functionality.
40
-
41
- ## Usage
42
-
43
- Hobbit applications are just instances of classes that inherits from
44
- `Hobbit::Base`, which complies the
45
- [Rack SPEC](http://rubydoc.info/github/rack/rack/master/file/SPEC).
46
-
47
- ### Hello World example
48
-
49
- Create a file called `app.rb`:
50
-
51
- ```ruby
52
- require 'hobbit'
53
-
54
- class App < Hobbit::Base
55
- get '/' do
56
- 'Hello World!'
57
- end
58
- end
59
- ```
60
-
61
- Create a `config.ru` file:
62
-
63
- ```ruby
64
- require './app'
65
-
66
- run App.new # or just `run App`
67
- ```
68
-
69
- Run it with `rackup`:
70
-
71
- ```bash
72
- $ rackup
73
- ```
74
-
75
- View your app at [http://localhost:9292](http://localhost:9292).
76
-
77
- ### Routes
78
-
79
- Every route is composed of a verb, a path (optional) and a block. When an
80
- incoming request matches a route, the block is executed and a response is sent
81
- back to the client. The return value of the block will be the `body` of the
82
- response. The `headers` and `status code` of the response will be calculated by
83
- `Hobbit::Response`, but you could modify it anyway you want it.
84
-
85
- See an example:
86
-
87
- ```ruby
88
- class App < Hobbit::Base
89
- get '/' do
90
- # ...
91
- end
92
-
93
- post '/' do
94
- # ...
95
- end
96
-
97
- put '/' do
98
- # ...
99
- end
100
-
101
- patch '/' do
102
- # ...
103
- end
104
-
105
- delete '/' do
106
- # ...
107
- end
108
-
109
- options '/' do
110
- # ...
111
- end
112
- end
113
- ```
114
-
115
- When a route gets called you have this methods available:
116
-
117
- * `env`: The Rack environment.
118
- * `request`: a `Hobbit::Request` instance.
119
- * `response`: a `Hobbit::Response` instance.
120
-
121
- And any other method defined in your application.
122
-
123
- #### Available methods
124
-
125
- * `delete`
126
- * `get`
127
- * `head`
128
- * `options`
129
- * `patch`
130
- * `post`
131
- * `put`
132
-
133
- **Note**: Since most browsers don't support methods other than **GET** and
134
- **POST** you must use the `Rack::MethodOverride` middleware. (See
135
- [Rack::MethodOverride](https://github.com/rack/rack/blob/master/lib/rack/methodoverride.rb)).
136
-
137
- #### Routes with parameters
138
-
139
- Besides the standard `GET` and `POST` parameters, you can have routes with
140
- parameters:
141
-
142
- ```ruby
143
- require 'hobbit'
144
-
145
- class App < Hobbit::Base
146
- # matches both /hi/hobbit and /hi/patricio
147
- get '/hi/:name' do
148
- # request.params is filled with the route paramters, like this:
149
- "Hello #{request.params[:name]}"
150
- end
151
- end
152
- ```
153
-
154
- #### Redirecting
155
-
156
- If you look at Hobbit implementation, you may notice that there is no
157
- `redirect` method (or similar). This is because such functionality is provided
158
- by [Rack::Response](https://github.com/rack/rack/blob/master/lib/rack/response.rb)
159
- and for now we [don't wan't to repeat ourselves](http://en.wikipedia.org/wiki/Don't_repeat_yourself)
160
- (obviously you can create an extension!). So, if you want to redirect to
161
- another route, do it like this:
162
-
163
- ```ruby
164
- require 'hobbit'
165
-
166
- class App < Hobbit::Base
167
- get '/' do
168
- response.redirect '/hi'
169
- end
170
-
171
- get '/hi' do
172
- 'Hello World!'
173
- end
174
- end
175
- ```
176
-
177
- #### Halting
178
-
179
- To immediately stop a request within route you can use `halt`.
180
-
181
- ```ruby
182
- require 'hobbit'
183
-
184
- class App < Hobbit::Base
185
- use Rack::Session::Cookie, secret: SecureRandom.hex(64)
186
-
187
- def session
188
- env['rack.session']
189
- end
190
-
191
- get '/' do
192
- response.status = 401
193
- halt response.finish
194
- end
195
- end
196
- ```
197
-
198
- ### Built on top of rack
199
-
200
- Each Hobbit application is a Rack stack (See this
201
- [blog post](http://m.onkey.org/ruby-on-rack-2-the-builder) for more
202
- information).
203
-
204
- #### Mapping applications
205
-
206
- You can mount any Rack application to the stack by using the `map` class
207
- method:
208
-
209
- ```ruby
210
- require 'hobbit'
211
-
212
- class InnerApp < Hobbit::Base
213
- # gets called when path_info = '/inner'
214
- get do
215
- 'Hello InnerApp!'
216
- end
217
- end
218
-
219
- class App < Hobbit::Base
220
- map('/inner') { run InnerApp.new }
221
-
222
- get '/' do
223
- 'Hello App!'
224
- end
225
- end
226
- ```
227
-
228
- #### Using middleware
229
-
230
- You can add any Rack middleware to the stack by using the `use` class method:
231
-
232
- ```ruby
233
- require 'hobbit'
234
-
235
- class App < Hobbit::Base
236
- use Rack::Session::Cookie, secret: SecureRandom.hex(64)
237
- use Rack::ShowExceptions
238
-
239
- def session
240
- env['rack.session']
241
- end
242
-
243
- get '/' do
244
- session[:name] = 'hobbit'
245
- end
246
-
247
- # more routes...
248
- end
249
-
250
- run App.new
251
- ```
252
-
253
- ### Security
254
-
255
- By default, Hobbit (nor Rack) comes without any protection against web
256
- attacks. The use of [rack-protection](https://github.com/rkh/rack-protection)
257
- is highly recommended:
258
-
259
- ```ruby
260
- require 'hobbit'
261
- require 'rack/protection'
262
- require 'securerandom'
263
-
264
- class App < Hobbit::Base
265
- use Rack::Session::Cookie, secret: SecureRandom.hex(64)
266
- use Rack::Protection
267
-
268
- get '/' do
269
- 'Hello World!'
270
- end
271
- end
272
- ```
273
-
274
- See the [rack-protection](https://github.com/rkh/rack-protection)
275
- documentation for futher information.
276
-
277
- ### Testing
278
-
279
- [rack-test](https://github.com/brynary/rack-test) is highly recommended. See
280
- an example:
281
-
282
- In `app.rb`:
283
-
284
- ```ruby
285
- require 'hobbit'
286
-
287
- class App < Hobbit::Base
288
- get '/' do
289
- 'Hello World!'
290
- end
291
- end
292
- ```
293
-
294
- In `app_spec.rb`:
295
-
296
- ```ruby
297
- require 'minitest/autorun'
298
- # imagine that app.rb and app_spec.rb are stored in the same directory
299
- require 'app'
300
-
301
- describe App do
302
- include Rack::Test::Methods
303
-
304
- def app
305
- App.new
306
- end
307
-
308
- describe 'GET /' do
309
- it 'must be ok' do
310
- get '/'
311
- last_response.must_be :ok?
312
- last_response.body.must_match /Hello World!/
313
- end
314
- end
315
- end
316
- ```
317
-
318
- See the [rack-test](https://github.com/brynary/rack-test) documentation
319
- for futher information.
320
-
321
- ### Extensions
322
-
323
- You can extend Hobbit by creating standard ruby modules. See an example:
324
-
325
- ```ruby
326
- module MyExtension
327
- def do_something
328
- # do something
329
- end
330
- end
331
-
332
- class App < Hobbit::Base
333
- include MyExtension
334
-
335
- get '/' do
336
- do_something
337
- 'Hello World!'
338
- end
339
- end
340
- ```
341
-
342
- #### Hobbit::Contrib
343
-
344
- [hobbit-contrib](https://github.com/patriciomacadden/hobbit-contrib) is a ruby
345
- gem that comes with a lot of hobbit extensions, such as:
346
-
347
- * `Hobbit::Render`: provides basic template rendering.
348
- * `Hobbit::Session`: provides helper methods for handling user sessions.
349
- * `Hobbit::Environment`: provides helper methods for handling application
350
- environments.
351
- * `Hobbit::Filter`: provides helper class methods for handling Sinatra-like
352
- filters.
353
- * `Hobbit::ErrorHandling`: provides helper class methods for handling
354
- Sinatra-like error handling.
355
-
356
- ... And many more!
357
-
358
- ## Community
359
-
360
- * [Wiki](https://github.com/patriciomacadden/hobbit/wiki): Guides, how-tos and recipes
361
- * IRC: [#hobbitrb](irc://chat.freenode.net/#hobbitrb) on [http://freenode.net](http://freenode.net)
362
-
363
- ## Presentations
364
-
365
- * Building web applications in Ruby, by [Krzysztof Wawer](https://github.com/wafcio)
366
- ([english](https://speakerdeck.com/wafcio/hobbit-english), [polish](https://speakerdeck.com/wafcio/hobbit))
367
-
368
- ## Contributing
369
-
370
- 1. Fork it
371
- 2. Create your feature branch (`git checkout -b my-new-feature`)
372
- 3. Commit your changes (`git commit -am 'Add some feature'`)
373
- 4. Push to the branch (`git push origin my-new-feature`)
374
- 5. Create new Pull Request
375
-
376
- ## License
377
-
378
- See the [LICENSE](https://github.com/patriciomacadden/hobbit/blob/master/LICENSE).