nyny 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1f24241aa6a73ebae5817c63be3aa5ced6be2d7d
4
- data.tar.gz: 2f357253186bbdaed025f103ddd21938a2a890a6
3
+ metadata.gz: b1377196ade715ab3d114440cf120a5596c81f67
4
+ data.tar.gz: 186f4d5433cb0171a41c07a0b686e40382622f95
5
5
  SHA512:
6
- metadata.gz: 471cb73f2ac5e5103e54cf4bce9e69db44d6f8f362664819c4475c638d284a7d25d3bb1a8751b59ee89e27fdcf20fdd166f419fccf1c1de8f6f1c67e90b0c2d2
7
- data.tar.gz: a768e13fda07d78d0002d782bf924905b72a66c7df73f86051cdef0bf7b75d3455d6f70ff2f51f84af4e4ac7440e5a2bf980eff5ae6d4e377c8be5713db54262
6
+ metadata.gz: 4d7cf903b0dfda2ea397680ac6cb8326e9e1a042733629452d9cb9576312da507eb10a54696afebf7b3c473337a88638eaafef60e15b72b92b90256db3f4ed25
7
+ data.tar.gz: 03ca191d2113dfc7bae9d674db8f75889127911df2ec38c1d3fedca30bb242739f6c16e7549e1b5e3c1c01ecb1c8d4d3d074161fba49b8dc1b7b4cd0a884489d
data/.gitignore CHANGED
@@ -1,20 +1,20 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- *.sqlite3
7
- *.sublime-project
8
- *.sublime-workspace
9
- Gemfile.lock
10
- InstalledFiles
11
- _yardoc
12
- coverage
13
- doc/
14
- lib/bundler/man
15
- pkg
16
- rdoc
17
- spec/reports
18
- test/tmp
19
- test/version_tmp
20
- tmp
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ *.sqlite3
7
+ *.sublime-project
8
+ *.sublime-workspace
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
data/.rspec CHANGED
@@ -1,2 +1,2 @@
1
- --color
2
- --order rand
1
+ --color
2
+ --order rand
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.0.0
1
+ 2.0.0
data/.travis.yml CHANGED
@@ -1,11 +1,11 @@
1
- ---
2
- rvm:
3
- - 1.9.2
4
- - 1.9.3
5
- - 2.0.0
6
- - jruby-19mode
7
- - jruby-20mode
8
-
9
- branches:
10
- only:
11
- - master
1
+ ---
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - jruby-19mode
7
+ - jruby-20mode
8
+
9
+ branches:
10
+ only:
11
+ - master
data/CHANGELOG CHANGED
@@ -1,40 +1,45 @@
1
- 3.0.0
2
- - Use Rack builder to shorten and simplify the code
3
- - Add support for namespaces by using the builder
4
- - Add ruby-prof as a development dependency
5
- - NYNY will return a Rack-like response on each request ([status, headers, body])
6
- - headers behave like a hash
7
- - cookies behave like a hash
8
- - added sprockets integration example
9
- - improved documentation
10
-
11
- 2.2.1
12
- - Added support for templates
13
-
14
- 2.1.1
15
- - After blocks will now be evaluated even if the request was halted
16
-
17
- 2.1.0
18
- - Add ability to define helpers with a block
19
- - Remove benchmark folder, and create a single benchmark file which can be
20
- executed easily
21
- - Simplified and optimized routing logic
22
- - Fixed root path processing when a NYNY app is mounted
23
- - Added Rails interop example
24
- - Added session example
25
- - Added NYNY.root
26
- - Added NYNY.env
27
- - NYNY will not show exceptions in production env
28
-
29
- 2.0.0
30
- - Simplified and improved RouteSignature implementation
31
- - Simplified and improved RequestScope implementation
32
- - Made response object available in RequestScope
33
- - removed .use_protection! (the rack-protection middleware can be easily
34
- used manually)
35
- - added support for extensions (using .register, which works the same way as in sinatra)
36
-
37
- 1.0.2
38
- - Add rack to runtime deps (@etehtsea)
39
-
40
- 1.0.0 Initial release
1
+ 3.0.1
2
+ - File SystemStackError when accessing missing param (@holies)
3
+
4
+ 3.0.0
5
+ - Use Rack builder to shorten and simplify the code
6
+ - Add support for namespaces by using the builder
7
+ - Add ruby-prof as a development dependency
8
+ - NYNY will return a Rack-like response on each request ([status, headers, body])
9
+ - headers behave like a hash
10
+ - cookies behave like a hash
11
+ - added sprockets integration example
12
+ - improved documentation
13
+ - Fixed inheritance behaviour for App (routes, filters, helpers, middlewares
14
+ will be passed down the inheritance chain)
15
+
16
+ 2.2.1
17
+ - Added support for templates
18
+
19
+ 2.1.1
20
+ - After blocks will now be evaluated even if the request was halted
21
+
22
+ 2.1.0
23
+ - Add ability to define helpers with a block
24
+ - Remove benchmark folder, and create a single benchmark file which can be
25
+ executed easily
26
+ - Simplified and optimized routing logic
27
+ - Fixed root path processing when a NYNY app is mounted
28
+ - Added Rails interop example
29
+ - Added session example
30
+ - Added NYNY.root
31
+ - Added NYNY.env
32
+ - NYNY will not show exceptions in production env
33
+
34
+ 2.0.0
35
+ - Simplified and improved RouteSignature implementation
36
+ - Simplified and improved RequestScope implementation
37
+ - Made response object available in RequestScope
38
+ - removed .use_protection! (the rack-protection middleware can be easily
39
+ used manually)
40
+ - added support for extensions (using .register, which works the same way as in sinatra)
41
+
42
+ 1.0.2
43
+ - Add rack to runtime deps (@etehtsea)
44
+
45
+ 1.0.0 Initial release
data/Gemfile CHANGED
@@ -1,8 +1,7 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
5
- group :test do
6
- gem 'coveralls', :require => false
7
- gem 'ruby-prof'
8
- end
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'coveralls', :require => false
7
+ end
data/LICENSE.txt CHANGED
@@ -1,22 +1,22 @@
1
- Copyright (c) 2013 Andrei Lisnic
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2013 Andrei Lisnic
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Performance.md CHANGED
@@ -1,46 +1,41 @@
1
- This output was generated by running benchmark.rb in repo root
2
- ```
3
- Comparing NYNY 2.2.1 with Sinatra 1.4.4
4
-
5
- Test: empty
6
- user system total real
7
- nyny: 0.070000 0.000000 0.070000 ( 0.067279)
8
- sinatra: 0.390000 0.020000 0.410000 ( 0.426609)
9
- NYNY is 6.34x faster than Sinatra in this test
10
-
11
- Test: hello world
12
- user system total real
13
- nyny: 0.110000 0.000000 0.110000 ( 0.103838)
14
- sinatra: 0.240000 0.010000 0.250000 ( 0.259423)
15
- NYNY is 2.50x faster than Sinatra in this test
16
-
17
- Test: filters
18
- user system total real
19
- nyny: 0.120000 0.000000 0.120000 ( 0.117447)
20
- sinatra: 0.250000 0.010000 0.260000 ( 0.257431)
21
- NYNY is 2.19x faster than Sinatra in this test
22
-
23
- Test: helpers
24
- user system total real
25
- nyny: 0.100000 0.000000 0.100000 ( 0.103084)
26
- sinatra: 0.250000 0.010000 0.260000 ( 0.257457)
27
- NYNY is 2.50x faster than Sinatra in this test
28
-
29
- Test: Url patterns
30
- user system total real
31
- nyny: 0.110000 0.000000 0.110000 ( 0.108765)
32
- sinatra: 0.270000 0.010000 0.280000 ( 0.282336)
33
- NYNY is 2.60x faster than Sinatra in this test
34
-
35
- Test: A lot o Plain routes
36
- user system total real
37
- nyny: 0.110000 0.000000 0.110000 ( 0.109565)
38
- sinatra: 0.250000 0.020000 0.270000 ( 0.265283)
39
- NYNY is 2.42x faster than Sinatra in this test
40
-
41
- Test: A lot of Pattern routes
42
- user system total real
43
- nyny: 0.130000 0.000000 0.130000 ( 0.125386)
44
- sinatra: 0.280000 0.010000 0.290000 ( 0.291068)
45
- NYNY is 2.32x faster than Sinatra in this test
46
- ```
1
+ This output was generated by running benchmark.rb in repo root
2
+ ```
3
+ Comparing NYNY 3.0.0 with Sinatra 1.4.4
4
+
5
+ Test: hello world
6
+ user system total real
7
+ nyny: 0.110000 0.000000 0.110000 ( 0.108916)
8
+ sinatra: 0.260000 0.010000 0.270000 ( 0.273225)
9
+ NYNY is 2.51x faster than Sinatra in this test
10
+
11
+ Test: filters
12
+ user system total real
13
+ nyny: 0.120000 0.000000 0.120000 ( 0.118976)
14
+ sinatra: 0.250000 0.010000 0.260000 ( 0.264279)
15
+ NYNY is 2.22x faster than Sinatra in this test
16
+
17
+ Test: helpers
18
+ user system total real
19
+ nyny: 0.100000 0.000000 0.100000 ( 0.105290)
20
+ sinatra: 0.240000 0.000000 0.240000 ( 0.249585)
21
+ NYNY is 2.37x faster than Sinatra in this test
22
+
23
+ Test: Url patterns
24
+ user system total real
25
+ nyny: 0.120000 0.000000 0.120000 ( 0.113535)
26
+ sinatra: 0.260000 0.020000 0.280000 ( 0.277098)
27
+ NYNY is 2.44x faster than Sinatra in this test
28
+
29
+ Test: A lot o Plain routes
30
+ user system total real
31
+ nyny: 0.120000 0.000000 0.120000 ( 0.113001)
32
+ sinatra: 0.250000 0.000000 0.250000 ( 0.262890)
33
+ NYNY is 2.33x faster than Sinatra in this test
34
+
35
+ Test: A lot of Pattern routes
36
+ user system total real
37
+ nyny: 0.130000 0.000000 0.130000 ( 0.133590)
38
+ sinatra: 0.270000 0.010000 0.280000 ( 0.284605)
39
+ NYNY is 2.13x faster than Sinatra in this test
40
+
41
+ ```
data/README.md CHANGED
@@ -1,423 +1,423 @@
1
- # New York, New York.
2
- (very) small Sinatra clone.
3
-
4
- [![Build Status](https://api.travis-ci.org/alisnic/nyny.png)](https://travis-ci.org/alisnic/nyny)
5
- [![Coverage Status](https://coveralls.io/repos/alisnic/nyny/badge.png)](https://coveralls.io/r/alisnic/nyny)
6
- [![Code Climate](https://codeclimate.com/repos/521b7ee513d637348712864a/badges/60e3637788bbac94f1cb/gpa.png)](https://codeclimate.com/repos/521b7ee513d637348712864a/feed)
7
- [![Dependency Status](https://gemnasium.com/alisnic/nyny.png)](https://gemnasium.com/alisnic/nyny)
8
- [![Gem Version](https://badge.fury.io/rb/nyny.png)](http://badge.fury.io/rb/nyny)
9
-
10
- ```ruby
11
- # myapp.rb
12
-
13
- require 'nyny'
14
- class App < NYNY::App
15
- get '/' do
16
- 'Hello world!'
17
- end
18
- end
19
-
20
- App.run!
21
- ```
22
-
23
- Install the gem:
24
-
25
- ```bash
26
- gem install nyny
27
- ```
28
-
29
- Run the file:
30
-
31
- ```bash
32
- ruby myapp.rb
33
- ```
34
-
35
- Open the browser at [http://localhost:9292](http://localhost:9292)
36
-
37
- - [TOP](#new-york-new-york)
38
- - [Motivation](#motivation)
39
- - [Philosophy](#philosophy)
40
- - [Why use NYNY instead of Sinatra](#why-use-nyny-instead-of-sinatra)
41
- - [Usage](#usage)
42
- - [Environment](#environment)
43
- - [Running](#running)
44
- - [Defining routes](#defining-routes)
45
- - [Namespaces](#namespaces)
46
- - [Templates](#templates)
47
- - [Request scope](#request-scope)
48
- - [Filters](#filters)
49
- - [Middleware](#middleware)
50
- - [Helpers](#helpers)
51
- - [Extensions](#extensions)
52
- - [FAQ](#f-a-q)
53
- - [Contributing](#contributing)
54
-
55
- # Motivation
56
- My efforts to write __NYNY__ started when I wanted to understand how __Sinatra__
57
- works, and stumbled upon the [base.rb][0]. The majority of the classes that
58
- are used by Sinatra are in one single file, which makes it nearly impossible
59
- for a new person to grasp.
60
-
61
- I wanted to understand how sinatra works, but the code was pretty challenging.
62
- So I decided I should re-implement the basic things Sinatra has.
63
- Thus, __NYNY__ was born.
64
-
65
- # Philosophy
66
- NYNY should have only the bare minimum to write basic web servers comfortably,
67
- everything else should be in a extension. It is also
68
- trivial to use NYNY to build large and complex apps, by writing multiple sub
69
- apps and using Rack to mount them, or by using those sub apps in the "main" app
70
- as middleware.
71
-
72
- # Why use NYNY instead of Sinatra
73
- - It's very small (~300 LOC), which is just a little overhead on top of Rack.
74
- - Sinatra is a drop-in replacement for NYNY. Anytime you feel that you need more,
75
- you can just change your app to inherit from `Sinatra::Base`, your code will
76
- still work, and you will be able to use any of the Sinatra features.
77
- - It's __~2 times faster__ than Sinatra (see [Performance][performance] for details)
78
- - You want to dig into the source code and change to your needs (NYNY's source code is more welcoming)
79
- - Each NYNY app is a Rack middleware, so it can be used inside of Sinatra, Rails, or any other Rack-based app.
80
-
81
- # Usage
82
-
83
- A NYNY app must _always_ be in a class which inherits from `NYNY::App`:
84
-
85
- ```ruby
86
- class App < NYNY::App
87
- get '/' do
88
- 'Hello, World'
89
- end
90
- end
91
- ```
92
-
93
- ## Environment
94
- To get the directory in which your app is running use `NYNY.root`
95
-
96
- ```ruby
97
- #/some/folder/server.rb
98
- require 'nyny'
99
- puts NYNY.root #=> /some/folder/
100
- ```
101
-
102
- To get NYNY's environment, use `NYNY.env`
103
-
104
- ```ruby
105
- #env.rb
106
- require 'nyny'
107
- puts NYNY.env
108
- puts NYNY.env.production?
109
- ```
110
-
111
- ```bash
112
- $ ruby env.rb
113
- development
114
- false
115
-
116
- $ ruby env.rb RACK_ENV=production
117
- production
118
- true
119
- ```
120
-
121
- ## Running
122
- There are two ways to run a NYNY app __directly__ [[?]](#middleware):
123
-
124
- - by requiring it in a `config.ru` file, and then passing it as argument to the
125
- Rack's `run` function:
126
-
127
- ```ruby
128
- # config.ru
129
-
130
- require 'app'
131
- run App.new
132
- ```
133
- - by using the `run!` method directly on the app class:
134
-
135
- ```ruby
136
- # app.rb
137
-
138
- # ...app class definition...
139
-
140
- App.run!
141
- ```
142
-
143
- `run!` takes the port number as optional argument (the default port is 9292).
144
- Also the `run!` method will include 2 default middlewares to make the
145
- development easier: Rack::CommonLogger and Rack::ShowExceptions.
146
- This will show all requests in the log, and will provide useful details
147
- in the case a error occurs during a request.
148
-
149
- ## Defining routes
150
-
151
- NYNY supports the following verbs for defining a route: delete, get, head,
152
- options, patch, post, put and trace.
153
-
154
- ```ruby
155
- class App < NYNY::App
156
- post '/' do
157
- 'You Posted, dude!'
158
- end
159
- end
160
- ```
161
-
162
- NYNY also suports basic URL patterns:
163
-
164
- ```ruby
165
- class App < NYNY::App
166
- get '/greet/:first_name/:last_name' do
167
- # the last expression in the block is _always_ considered the response body.
168
- "Hello #{params[:first_name]} #{params[:last_name]}!"
169
- end
170
- end
171
- ```
172
-
173
- you can also tell NYNY to match a regex for a path:
174
-
175
- ```ruby
176
- class App < NYNY::App
177
- get /html/ do
178
- 'Your URL contains html!'
179
- end
180
- end
181
- ```
182
-
183
- Each block that is passed to a route definition is evaluated in the context of
184
- a request scope. See below what methods are available there.
185
-
186
- ## Namespaces
187
- You can define namespaces for routes in NYNY. Each namespace is an isolated
188
- app, which means that you can use the same api that you use in your top app there:
189
-
190
- ```ruby
191
- class App < NYNY::App
192
- get '/' do
193
- 'Hello'
194
- end
195
-
196
- namespace '/nested' do
197
- use SomeMiddleware
198
- helpers SomeHelpers
199
-
200
- get '/' do # this will be accessible at '/nested'
201
- 'Hello from namespace!'
202
- end
203
- end
204
- end
205
- ```
206
-
207
- ## Templates
208
- NYNY can render templates, all you need is to call the `render` function:
209
- ```ruby
210
- class App < NYNY::App
211
- get '/' do
212
- render 'index.erb'
213
- end
214
- end
215
- ```
216
- There are 2 ways to pass data to the template:
217
-
218
- Via a instance variable:
219
- ```ruby
220
- class App < NYNY::App
221
- get '/' do
222
- @foo = 'bar' #access it as @foo in template
223
- render 'index.erb'
224
- end
225
- end
226
- ```
227
-
228
- Or via a local variable:
229
- ```ruby
230
- class App < NYNY::App
231
- get '/' do
232
- render 'index.erb', :foo => 'bar' #access it as foo in template
233
- end
234
- end
235
- ```
236
-
237
- To render a template with a layout, you need to render both files. It's best
238
- to create a helper for that:
239
- ```ruby
240
- class App < NYNY::App
241
- helpers do
242
- def render_with_layout *args
243
- render 'layout.erb' do
244
- render *args
245
- end
246
- end
247
- end
248
-
249
- get '/' do
250
- render_with_layout 'index.erb'
251
- end
252
- end
253
- ```
254
- NYNY uses [Tilt][tilt] for templating, so the list of supported engines is pretty complete.
255
-
256
- ## Request scope
257
- As was said above, when you pass a block to a route definition,
258
- that block is evaluated in the context of a [RequestScope][2].
259
- This means that several methods/objects available inside that block:
260
-
261
- - `request` - A `Rack::Request` object which encapsulates the request
262
- to that route. (see [Rack::Request documentation][3] for more info)
263
- - `response` - A `Rack::Response` object which encapsulates the response.
264
- Additionally, NYNY's response exposes 2 more methods in addition to Rack's ones.
265
- (see [primitives.rb][primitivesrb])
266
- - `params` - a hash which contains both POST body params and GET querystring params.
267
- - `headers` - a hash with the response headers
268
- (ex: `headers['Content-Type'] = 'text/html'`)
269
- - `status` - allows you to set the status of the response (ex: `status 403`)
270
- - `redirect_to` - sets the response to redirect
271
- (ex: `redirect_to 'http://google.com'`)
272
- - `cookies` - a hash which allows you to access/modify/remove cookies
273
- (ex: `cookies[:foo] = 'bar'` or `cookies.delete[:foo]`)
274
- - `session` - a hash which allows you to access/modify/remove session variables
275
- (ex: `session[:foo] = 'bar'`)
276
- - `halt` - allows you to instantly return a response, interrupting current
277
- handler execution (see [halt][halt-definition])
278
-
279
- ## Filters
280
-
281
- Unlike Sinatra, NYNY supports only "generic" before and after filters.
282
- This means that you can't declare a filter to execute depending on a URL pattern.
283
- However, you can obtain the same effect by calling next in a before block
284
- if the request.path matches a pattern.
285
-
286
- ```ruby
287
- class App < NYNY::App
288
- before do
289
- next unless /html/ =~ request.path
290
- headers['Content-Type'] = 'text/html'
291
- end
292
-
293
- after do
294
- puts response.inspect
295
- end
296
-
297
- get '/' do
298
- 'hello'
299
- end
300
- end
301
- ```
302
-
303
- ## Middleware
304
-
305
- A NYNY app is a Rack middleware, which means that it can be used inside
306
- Sinatra, Rails, or any other Rack-based app:
307
-
308
- ```ruby
309
- class MyApp < Sinatra::Base
310
- use MyNYNYApp
311
- end
312
- ```
313
-
314
- NYNY also supports middleware itself, and that means you can use Rack middleware
315
- (or a Sinatra app) inside a NYNY app:
316
-
317
- ```ruby
318
- class App < NYNY::App
319
- # this will serve all the files in the "public" folder
320
- use Rack::Static :url => ['public']
321
- use SinatraApp
322
- end
323
- ```
324
-
325
- I recommend looking at [the list of Rack middlewares][rack-middleware]
326
-
327
- ## Helpers
328
-
329
- NYNY supports helpers as Sinatra does:
330
-
331
- ```ruby
332
- class App < NYNY::App
333
- helpers MyHelperModule
334
- helpers do
335
- def using_a_block_to_define_helper
336
- true
337
- end
338
- end
339
- end
340
- ```
341
-
342
-
343
- Using a helper implies that the helper module is included in the [RequestScope][2],
344
- and that all the methods in that module will be available inside a route
345
- definition block.
346
-
347
- ## Extensions
348
-
349
- Since version 2.0.0, NYNY added support for extensions.
350
- This makes possible to include helpers, middlewares and custom app class
351
- methods inside a single module:
352
-
353
- ```ruby
354
- module MyKewlExtension
355
- class Middleware
356
- def initialize app
357
- @app = app
358
- end
359
-
360
- def call env
361
- env['KEWL'] = true
362
- @app.call(env) if @app
363
- end
364
- end
365
-
366
- module Helpers
367
- def the_ultimate_answer
368
- 42
369
- end
370
- end
371
-
372
- def get_or_post route, &block
373
- get route, &block
374
- post route, &block
375
- end
376
-
377
- def self.registered app
378
- app.use Middleware
379
- app.helpers Helpers
380
-
381
- app.get_or_post '/' do
382
- "After many years of hard computation, the answer is #{the_ultimate_answer}"
383
- end
384
- end
385
- end
386
-
387
- class App < NYNY::App
388
- register MyKewlExtension
389
- end
390
-
391
- App.run!
392
- ```
393
-
394
- By default, the App class will `extend` the provided extension module.
395
- Optionally, an extension can add a `registered` method, which will be invoked
396
- once the extension is registered. That method will be called with the app class
397
- as a parameter.
398
-
399
- Since NYNY has the same extension interface as Sinatra, some Sinatra extensions
400
- might work with NYNY, although that is not guaranteed. However, an extension
401
- written for NYNY will always work with Sinatra. (Forward compatible)
402
-
403
- # F. A. Q.
404
- TBD.
405
-
406
- # Contributing
407
-
408
- 1. Fork it
409
- 2. Create your feature branch (`git checkout -b my-new-feature`)
410
- 3. Commit your changes (`git commit -am 'Add some feature'`)
411
- 4. Push to the branch (`git push origin my-new-feature`)
412
- 5. Create new Pull Request
413
-
414
- [0]: https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb
415
- [1]: https://github.com/sinatra/sinatra/pull/716
416
- [2]: https://github.com/alisnic/nyny/blob/master/lib/nyny/request_scope.rb
417
- [3]: http://rack.rubyforge.org/doc/classes/Rack/Request.html
418
- [4]: http://rack.rubyforge.org/doc/classes/Rack/Response.html
419
- [performance]: https://github.com/alisnic/nyny/blob/master/Performance.md
420
- [rack-middleware]: https://github.com/rack/rack/wiki/List-of-Middleware
421
- [halt-definition]: https://github.com/alisnic/nyny/blob/master/lib/nyny/request_scope.rb#L36
422
- [primitivesrb]: https://github.com/alisnic/nyny/blob/master/lib/nyny/primitives.rb
423
- [tilt]: https://github.com/rtomayko/tilt
1
+ # New York, New York.
2
+ (very) small Sinatra clone.
3
+
4
+ [![Build Status](https://api.travis-ci.org/alisnic/nyny.png)](https://travis-ci.org/alisnic/nyny)
5
+ [![Coverage Status](https://coveralls.io/repos/alisnic/nyny/badge.png)](https://coveralls.io/r/alisnic/nyny)
6
+ [![Code Climate](https://codeclimate.com/repos/521b7ee513d637348712864a/badges/60e3637788bbac94f1cb/gpa.png)](https://codeclimate.com/repos/521b7ee513d637348712864a/feed)
7
+ [![Dependency Status](https://gemnasium.com/alisnic/nyny.png)](https://gemnasium.com/alisnic/nyny)
8
+ [![Gem Version](https://badge.fury.io/rb/nyny.png)](http://badge.fury.io/rb/nyny)
9
+
10
+ ```ruby
11
+ # myapp.rb
12
+
13
+ require 'nyny'
14
+ class App < NYNY::App
15
+ get '/' do
16
+ 'Hello world!'
17
+ end
18
+ end
19
+
20
+ App.run!
21
+ ```
22
+
23
+ Install the gem:
24
+
25
+ ```bash
26
+ gem install nyny
27
+ ```
28
+
29
+ Run the file:
30
+
31
+ ```bash
32
+ ruby myapp.rb
33
+ ```
34
+
35
+ Open the browser at [http://localhost:9292](http://localhost:9292)
36
+
37
+ - [TOP](#new-york-new-york)
38
+ - [Motivation](#motivation)
39
+ - [Philosophy](#philosophy)
40
+ - [Why use NYNY instead of Sinatra](#why-use-nyny-instead-of-sinatra)
41
+ - [Usage](#usage)
42
+ - [Environment](#environment)
43
+ - [Running](#running)
44
+ - [Defining routes](#defining-routes)
45
+ - [Namespaces](#namespaces)
46
+ - [Templates](#templates)
47
+ - [Request scope](#request-scope)
48
+ - [Filters](#filters)
49
+ - [Middleware](#middleware)
50
+ - [Helpers](#helpers)
51
+ - [Extensions](#extensions)
52
+ - [FAQ](#f-a-q)
53
+ - [Contributing](#contributing)
54
+
55
+ # Motivation
56
+ My efforts to write __NYNY__ started when I wanted to understand how __Sinatra__
57
+ works, and stumbled upon the [base.rb][0]. The majority of the classes that
58
+ are used by Sinatra are in one single file, which makes it nearly impossible
59
+ for a new person to grasp.
60
+
61
+ I wanted to understand how sinatra works, but the code was pretty challenging.
62
+ So I decided I should re-implement the basic things Sinatra has.
63
+ Thus, __NYNY__ was born.
64
+
65
+ # Philosophy
66
+ NYNY should have only the bare minimum to write basic web servers comfortably,
67
+ everything else should be in a extension. It is also
68
+ trivial to use NYNY to build large and complex apps, by writing multiple sub
69
+ apps and using Rack to mount them, or by using those sub apps in the "main" app
70
+ as middleware.
71
+
72
+ # Why use NYNY instead of Sinatra
73
+ - It's very small (~300 LOC), which is just a little overhead on top of Rack.
74
+ - Sinatra is a drop-in replacement for NYNY. Anytime you feel that you need more,
75
+ you can just change your app to inherit from `Sinatra::Base`, your code will
76
+ still work, and you will be able to use any of the Sinatra features.
77
+ - It's __~2 times faster__ than Sinatra (see [Performance][performance] for details)
78
+ - You want to dig into the source code and change to your needs (NYNY's source code is more welcoming)
79
+ - Each NYNY app is a Rack middleware, so it can be used inside of Sinatra, Rails, or any other Rack-based app.
80
+
81
+ # Usage
82
+
83
+ A NYNY app must _always_ be in a class which inherits from `NYNY::App`:
84
+
85
+ ```ruby
86
+ class App < NYNY::App
87
+ get '/' do
88
+ 'Hello, World'
89
+ end
90
+ end
91
+ ```
92
+
93
+ ## Environment
94
+ To get the directory in which your app is running use `NYNY.root`
95
+
96
+ ```ruby
97
+ #/some/folder/server.rb
98
+ require 'nyny'
99
+ puts NYNY.root #=> /some/folder/
100
+ ```
101
+
102
+ To get NYNY's environment, use `NYNY.env`
103
+
104
+ ```ruby
105
+ #env.rb
106
+ require 'nyny'
107
+ puts NYNY.env
108
+ puts NYNY.env.production?
109
+ ```
110
+
111
+ ```bash
112
+ $ ruby env.rb
113
+ development
114
+ false
115
+
116
+ $ ruby env.rb RACK_ENV=production
117
+ production
118
+ true
119
+ ```
120
+
121
+ ## Running
122
+ There are two ways to run a NYNY app __directly__ [[?]](#middleware):
123
+
124
+ - by requiring it in a `config.ru` file, and then passing it as argument to the
125
+ Rack's `run` function:
126
+
127
+ ```ruby
128
+ # config.ru
129
+
130
+ require 'app'
131
+ run App.new
132
+ ```
133
+ - by using the `run!` method directly on the app class:
134
+
135
+ ```ruby
136
+ # app.rb
137
+
138
+ # ...app class definition...
139
+
140
+ App.run!
141
+ ```
142
+
143
+ `run!` takes the port number as optional argument (the default port is 9292).
144
+ Also the `run!` method will include 2 default middlewares to make the
145
+ development easier: Rack::CommonLogger and Rack::ShowExceptions.
146
+ This will show all requests in the log, and will provide useful details
147
+ in the case a error occurs during a request.
148
+
149
+ ## Defining routes
150
+
151
+ NYNY supports the following verbs for defining a route: delete, get, head,
152
+ options, patch, post, put and trace.
153
+
154
+ ```ruby
155
+ class App < NYNY::App
156
+ post '/' do
157
+ 'You Posted, dude!'
158
+ end
159
+ end
160
+ ```
161
+
162
+ NYNY also suports basic URL patterns:
163
+
164
+ ```ruby
165
+ class App < NYNY::App
166
+ get '/greet/:first_name/:last_name' do
167
+ # the last expression in the block is _always_ considered the response body.
168
+ "Hello #{params[:first_name]} #{params[:last_name]}!"
169
+ end
170
+ end
171
+ ```
172
+
173
+ you can also tell NYNY to match a regex for a path:
174
+
175
+ ```ruby
176
+ class App < NYNY::App
177
+ get /html/ do
178
+ 'Your URL contains html!'
179
+ end
180
+ end
181
+ ```
182
+
183
+ Each block that is passed to a route definition is evaluated in the context of
184
+ a request scope. See below what methods are available there.
185
+
186
+ ## Namespaces
187
+ You can define namespaces for routes in NYNY. Each namespace is an isolated
188
+ app, which means that you can use the same api that you use in your top app there:
189
+
190
+ ```ruby
191
+ class App < NYNY::App
192
+ get '/' do
193
+ 'Hello'
194
+ end
195
+
196
+ namespace '/nested' do
197
+ use SomeMiddleware
198
+ helpers SomeHelpers
199
+
200
+ get '/' do # this will be accessible at '/nested'
201
+ 'Hello from namespace!'
202
+ end
203
+ end
204
+ end
205
+ ```
206
+
207
+ ## Templates
208
+ NYNY can render templates, all you need is to call the `render` function:
209
+ ```ruby
210
+ class App < NYNY::App
211
+ get '/' do
212
+ render 'index.erb'
213
+ end
214
+ end
215
+ ```
216
+ There are 2 ways to pass data to the template:
217
+
218
+ Via a instance variable:
219
+ ```ruby
220
+ class App < NYNY::App
221
+ get '/' do
222
+ @foo = 'bar' #access it as @foo in template
223
+ render 'index.erb'
224
+ end
225
+ end
226
+ ```
227
+
228
+ Or via a local variable:
229
+ ```ruby
230
+ class App < NYNY::App
231
+ get '/' do
232
+ render 'index.erb', :foo => 'bar' #access it as foo in template
233
+ end
234
+ end
235
+ ```
236
+
237
+ To render a template with a layout, you need to render both files. It's best
238
+ to create a helper for that:
239
+ ```ruby
240
+ class App < NYNY::App
241
+ helpers do
242
+ def render_with_layout *args
243
+ render 'layout.erb' do
244
+ render *args
245
+ end
246
+ end
247
+ end
248
+
249
+ get '/' do
250
+ render_with_layout 'index.erb'
251
+ end
252
+ end
253
+ ```
254
+ NYNY uses [Tilt][tilt] for templating, so the list of supported engines is pretty complete.
255
+
256
+ ## Request scope
257
+ As was said above, when you pass a block to a route definition,
258
+ that block is evaluated in the context of a [RequestScope][2].
259
+ This means that several methods/objects available inside that block:
260
+
261
+ - `request` - A `Rack::Request` object which encapsulates the request
262
+ to that route. (see [Rack::Request documentation][3] for more info)
263
+ - `response` - A `Rack::Response` object which encapsulates the response.
264
+ Additionally, NYNY's response exposes 2 more methods in addition to Rack's ones.
265
+ (see [primitives.rb][primitivesrb])
266
+ - `params` - a hash which contains both POST body params and GET querystring params.
267
+ - `headers` - a hash with the response headers
268
+ (ex: `headers['Content-Type'] = 'text/html'`)
269
+ - `status` - allows you to set the status of the response (ex: `status 403`)
270
+ - `redirect_to` - sets the response to redirect
271
+ (ex: `redirect_to 'http://google.com'`)
272
+ - `cookies` - a hash which allows you to access/modify/remove cookies
273
+ (ex: `cookies[:foo] = 'bar'` or `cookies.delete[:foo]`)
274
+ - `session` - a hash which allows you to access/modify/remove session variables
275
+ (ex: `session[:foo] = 'bar'`)
276
+ - `halt` - allows you to instantly return a response, interrupting current
277
+ handler execution (see [halt][halt-definition])
278
+
279
+ ## Filters
280
+
281
+ Unlike Sinatra, NYNY supports only "generic" before and after filters.
282
+ This means that you can't declare a filter to execute depending on a URL pattern.
283
+ However, you can obtain the same effect by calling next in a before block
284
+ if the request.path matches a pattern.
285
+
286
+ ```ruby
287
+ class App < NYNY::App
288
+ before do
289
+ next unless /html/ =~ request.path
290
+ headers['Content-Type'] = 'text/html'
291
+ end
292
+
293
+ after do
294
+ puts response.inspect
295
+ end
296
+
297
+ get '/' do
298
+ 'hello'
299
+ end
300
+ end
301
+ ```
302
+
303
+ ## Middleware
304
+
305
+ A NYNY app is a Rack middleware, which means that it can be used inside
306
+ Sinatra, Rails, or any other Rack-based app:
307
+
308
+ ```ruby
309
+ class MyApp < Sinatra::Base
310
+ use MyNYNYApp
311
+ end
312
+ ```
313
+
314
+ NYNY also supports middleware itself, and that means you can use Rack middleware
315
+ (or a Sinatra app) inside a NYNY app:
316
+
317
+ ```ruby
318
+ class App < NYNY::App
319
+ # this will serve all the files in the "public" folder
320
+ use Rack::Static :url => ['public']
321
+ use SinatraApp
322
+ end
323
+ ```
324
+
325
+ I recommend looking at [the list of Rack middlewares][rack-middleware]
326
+
327
+ ## Helpers
328
+
329
+ NYNY supports helpers as Sinatra does:
330
+
331
+ ```ruby
332
+ class App < NYNY::App
333
+ helpers MyHelperModule
334
+ helpers do
335
+ def using_a_block_to_define_helper
336
+ true
337
+ end
338
+ end
339
+ end
340
+ ```
341
+
342
+
343
+ Using a helper implies that the helper module is included in the [RequestScope][2],
344
+ and that all the methods in that module will be available inside a route
345
+ definition block.
346
+
347
+ ## Extensions
348
+
349
+ Since version 2.0.0, NYNY added support for extensions.
350
+ This makes possible to include helpers, middlewares and custom app class
351
+ methods inside a single module:
352
+
353
+ ```ruby
354
+ module MyKewlExtension
355
+ class Middleware
356
+ def initialize app
357
+ @app = app
358
+ end
359
+
360
+ def call env
361
+ env['KEWL'] = true
362
+ @app.call(env) if @app
363
+ end
364
+ end
365
+
366
+ module Helpers
367
+ def the_ultimate_answer
368
+ 42
369
+ end
370
+ end
371
+
372
+ def get_or_post route, &block
373
+ get route, &block
374
+ post route, &block
375
+ end
376
+
377
+ def self.registered app
378
+ app.use Middleware
379
+ app.helpers Helpers
380
+
381
+ app.get_or_post '/' do
382
+ "After many years of hard computation, the answer is #{the_ultimate_answer}"
383
+ end
384
+ end
385
+ end
386
+
387
+ class App < NYNY::App
388
+ register MyKewlExtension
389
+ end
390
+
391
+ App.run!
392
+ ```
393
+
394
+ By default, the App class will `extend` the provided extension module.
395
+ Optionally, an extension can add a `registered` method, which will be invoked
396
+ once the extension is registered. That method will be called with the app class
397
+ as a parameter.
398
+
399
+ Since NYNY has the same extension interface as Sinatra, some Sinatra extensions
400
+ might work with NYNY, although that is not guaranteed. However, an extension
401
+ written for NYNY will always work with Sinatra. (Forward compatible)
402
+
403
+ # F. A. Q.
404
+ TBD.
405
+
406
+ # Contributing
407
+
408
+ 1. Fork it
409
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
410
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
411
+ 4. Push to the branch (`git push origin my-new-feature`)
412
+ 5. Create new Pull Request
413
+
414
+ [0]: https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb
415
+ [1]: https://github.com/sinatra/sinatra/pull/716
416
+ [2]: https://github.com/alisnic/nyny/blob/master/lib/nyny/request_scope.rb
417
+ [3]: http://rack.rubyforge.org/doc/classes/Rack/Request.html
418
+ [4]: http://rack.rubyforge.org/doc/classes/Rack/Response.html
419
+ [performance]: https://github.com/alisnic/nyny/blob/master/Performance.md
420
+ [rack-middleware]: https://github.com/rack/rack/wiki/List-of-Middleware
421
+ [halt-definition]: https://github.com/alisnic/nyny/blob/master/lib/nyny/request_scope.rb#L36
422
+ [primitivesrb]: https://github.com/alisnic/nyny/blob/master/lib/nyny/primitives.rb
423
+ [tilt]: https://github.com/rtomayko/tilt