nyny 2.2.1 → 3.0.0

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: 6dd6eb95721d78c86e3bbb400a9840369d02e438
4
- data.tar.gz: d85151c9759b13ef449ca5b37fecf4575a486a84
3
+ metadata.gz: 1f24241aa6a73ebae5817c63be3aa5ced6be2d7d
4
+ data.tar.gz: 2f357253186bbdaed025f103ddd21938a2a890a6
5
5
  SHA512:
6
- metadata.gz: 5cd94aac928361668da4b20ee7d23609749d47d4545b7fc13a52f51fae4421c8a7a79655ec96488a90899f13b582bd6de6d9308842b7cd9b95a8f664fb3cce37
7
- data.tar.gz: 3d6a67e6dfa7052770ac7b9199863d6d4ad2890d13a3d28be60aaf36ffba7da6fb6be157647a881a8ec1e9f2b49696f5687dac548a5135f41738e12ee77327f6
6
+ metadata.gz: 471cb73f2ac5e5103e54cf4bce9e69db44d6f8f362664819c4475c638d284a7d25d3bb1a8751b59ee89e27fdcf20fdd166f419fccf1c1de8f6f1c67e90b0c2d2
7
+ data.tar.gz: a768e13fda07d78d0002d782bf924905b72a66c7df73f86051cdef0bf7b75d3455d6f70ff2f51f84af4e4ac7440e5a2bf980eff5ae6d4e377c8be5713db54262
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,12 +1,11 @@
1
- ---
2
- rvm:
3
- - 1.9.2
4
- - 1.9.3
5
- - 2.0.0
6
- - rbx-19mode
7
- - jruby-19mode
8
- - jruby-20mode
9
-
10
- branches:
11
- only:
12
- - 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,27 +1,40 @@
1
- 2.1.1
2
- - After blocks will now be evaluated even if the request was halted
3
-
4
- 2.1.0
5
- - Add ability to define helpers with a block
6
- - Remove benchmark folder, and create a single benchmark file which can be
7
- executed easily
8
- - Simplified and optimized routing logic
9
- - Fixed root path processing when a NYNY app is mounted
10
- - Added Rails interop example
11
- - Added session example
12
- - Added NYNY.root
13
- - Added NYNY.env
14
- - NYNY will not show exceptions in production env
15
-
16
- 2.0.0
17
- - Simplified and improved RouteSignature implementation
18
- - Simplified and improved RequestScope implementation
19
- - Made response object available in RequestScope
20
- - removed .use_protection! (the rack-protection middleware can be easily
21
- used manually)
22
- - added support for extensions (using .register, which works the same way as in sinatra)
23
-
24
- 1.0.2
25
- - Add rack to runtime deps (@etehtsea)
26
-
27
- 1.0.0 Initial release
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
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
5
- group :test do
6
- gem 'coveralls', :require => false
7
- gem 'rack-protection'
8
- end
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'coveralls', :require => false
7
+ gem 'ruby-prof'
8
+ 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,44 +1,46 @@
1
- This output was generated by running benchmark.rb in repo root
2
-
3
- Comparing NYNY 2.1.0 with Sinatra 1.4.3
4
-
5
- Test: empty
6
- ```
7
- user system total real
8
- nyny: 0.060000 0.010000 0.070000 ( 0.063841)
9
- sinatra: 0.380000 0.000000 0.380000 ( 0.392611)
10
- ```
11
- NYNY is **6.15x** faster than Sinatra in this test
12
-
13
- Test: hello world
14
- ```
15
- user system total real
16
- nyny: 0.100000 0.000000 0.100000 ( 0.099356)
17
- sinatra: 0.250000 0.010000 0.260000 ( 0.253724)
18
- ```
19
- NYNY is **2.55x** faster than Sinatra in this test
20
-
21
- Test: filters
22
- ```
23
- user system total real
24
- nyny: 0.090000 0.000000 0.090000 ( 0.097938)
25
- sinatra: 0.260000 0.000000 0.260000 ( 0.259718)
26
- ```
27
- NYNY is **2.65x** faster than Sinatra in this test
28
-
29
- Test: helpers
30
- ```
31
- user system total real
32
- nyny: 0.090000 0.000000 0.090000 ( 0.090412)
33
- sinatra: 0.240000 0.010000 0.250000 ( 0.239332)
34
- ```
35
- NYNY is **2.65x** faster than Sinatra in this test
36
-
37
- Test: Url patterns
38
- ```
39
- user system total real
40
- nyny: 0.100000 0.000000 0.100000 ( 0.104926)
41
- sinatra: 0.260000 0.000000 0.260000 ( 0.268531)
42
- ```
43
- NYNY is **2.56x** faster than Sinatra in this test
44
-
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
+ ```
data/README.md CHANGED
@@ -1,381 +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
- - [Templates](#templates)
46
- - [Request scope](#request-scope)
47
- - [Filters](#filters)
48
- - [Middleware](#middleware)
49
- - [Helpers](#helpers)
50
- - [Extensions](#extensions)
51
- - [FAQ](#f-a-q)
52
- - [Contributing](#contributing)
53
-
54
- # Motivation
55
- My efforts to write __NYNY__ started when I wanted to understand how __Sinatra__
56
- works, and stumbled upon the [base.rb][0]. The majority of the classes that
57
- are used by sinatra are in one single file, which makes it nearly impossible
58
- for a new person to grasp.
59
-
60
- I wanted to understand how sinatra works, but the code was pretty challenging.
61
- So I decided I should re-implement the basic things Sinatra has.
62
- Thus, __NYNY__ was born.
63
-
64
- # Philosophy
65
- NYNY should have only the bare minimum to write basic web servers comfortably,
66
- everything else should be in a extension. It is also
67
- trivial to use NYNY to build large and complex apps, by writing multiple sub
68
- apps and using Rack to mount them, or by using those sub apps in the "main" app
69
- as middleware.
70
-
71
- # Why use NYNY instead of Sinatra
72
- - It's very small (<300 LOC), which is just a little overhead on top of Rack.
73
- - Sinatra is a drop-in replacement for NYNY. Anytime you feel that you need more,
74
- you can just change your app to inherit from `Sinatra::Base`, your code will
75
- still work, and you will be able to use any of the Sinatra features.
76
- - It's __~2 times faster__ than Sinatra (see [Performance][performance] for details)
77
- - You want to dig into the source code and change to your needs (NYNY's source code is more welcoming)
78
- - Each NYNY app is a Rack middleware, so it can be used inside of Sinatra, Rails, or any other Rack-based app.
79
-
80
- # Usage
81
-
82
- A NYNY app must _always_ be in a class which inherits from `NYNY::App`:
83
-
84
- ```ruby
85
- class App < NYNY::App
86
- get '/' do
87
- 'Hello, World'
88
- end
89
- end
90
- ```
91
-
92
- ## Environment
93
- To get the directory in which your app is running use `NYNY.root`
94
-
95
- ```ruby
96
- #/some/folder/server.rb
97
- require 'nyny'
98
- puts NYNY.root #=> /some/folder/
99
- ```
100
-
101
- To get NYNY's environment, use `NYNY.env`
102
-
103
- ```ruby
104
- #env.rb
105
- require 'nyny'
106
- puts NYNY.env
107
- puts NYNY.env.production?
108
- ```
109
-
110
- ```bash
111
- $ ruby env.rb
112
- development
113
- false
114
-
115
- $ ruby env.rb RACK_ENV=production
116
- production
117
- true
118
- ```
119
-
120
- ## Running
121
- There are two ways to run a NYNY app __directly__ [[?]](#middleware):
122
-
123
- - by requiring it in a `config.ru` file, and then passing it as argument to the
124
- Rack's `run` function:
125
-
126
- ```ruby
127
- # config.ru
128
-
129
- require 'app'
130
- run App.new
131
- ```
132
- - by using the `run!` method directly on the app class:
133
-
134
- ```ruby
135
- # app.rb
136
-
137
- # ...app class definition...
138
-
139
- App.run!
140
- ```
141
-
142
- `run!` takes the port number as optional argument (the default port is 9292).
143
- Also the `run!` method will include 2 default middlewares to make the
144
- development easier: Rack::CommonLogger and Rack::ShowExceptions.
145
- This will show all requests in the log, and will provide useful details
146
- in the case a error occurs during a request.
147
-
148
- ## Defining routes
149
-
150
- NYNY supports the following verbs for defining a route: delete, get, head,
151
- options, patch, post, put and trace.
152
-
153
- ```ruby
154
- class App < NYNY::App
155
- post '/' do
156
- 'You Posted, dude!'
157
- end
158
- end
159
- ```
160
-
161
- NYNY also suports basic URL patterns:
162
-
163
- ```ruby
164
- class App < NYNY::App
165
- get '/greet/:first_name/:last_name' do
166
- # the last expression in the block is _always_ considered the response body.
167
- "Hello #{params[:first_name]} #{params[:last_name]}!"
168
- end
169
- end
170
- ```
171
-
172
- you can also tell NYNY to match a regex for a path:
173
-
174
- ```ruby
175
- class App < NYNY::App
176
- get /html/ do
177
- 'Your URL contains html!'
178
- end
179
- end
180
- ```
181
-
182
- Each block that is passed to a route definition is evaluated in the context of
183
- a request scope. See below what methods are available there.
184
-
185
- ## Templates
186
- NYNY can render templates, all you need is to call the `render` function:
187
- ```ruby
188
- class App < NYNY::App
189
- get '/' do
190
- render 'index.erb'
191
- end
192
- end
193
- ```
194
- There are 2 ways to pass data to the template:
195
-
196
- Via a instance variable:
197
- ```ruby
198
- class App < NYNY::App
199
- get '/' do
200
- @foo = 'bar' #access it as @foo in template
201
- render 'index.erb'
202
- end
203
- end
204
- ```
205
-
206
- Or via a local variable:
207
- ```ruby
208
- class App < NYNY::App
209
- get '/' do
210
- render 'index.erb', :foo => 'bar' #access it as foo in template
211
- end
212
- end
213
- ```
214
-
215
- ## Request scope
216
- As was said above, when you pass a block to a route definition,
217
- that block is evaluated in the context of a [RequestScope][2].
218
- This means that several methods/objects available inside that block:
219
-
220
- - `request` - A `Rack::Request` object which encapsulates the request
221
- to that route. (see [Rack::Request documentation][3] for more info)
222
- - `response` - A `Rack::Response` object which encapsulates the response.
223
- Additionally, NYNY's response exposes 2 more methods in addition to Rack's ones.
224
- (see [primitives.rb][primitivesrb])
225
- - `params` - a hash which contains both POST body params and GET querystring params.
226
- - `headers` - allows you to read/add headers to the response
227
- (ex: `headers 'Content-Type' => 'text/html'`)
228
- - `status` - allows you to set the status of the response (ex: `status 403`)
229
- - `redirect_to` - sets the response to redirect
230
- (ex: `redirect_to 'http://google.com'`)
231
- - `cookies` - a hash which allows you to access/modify/remove cookies
232
- (ex: `cookies[:foo] = 'bar'`)
233
- - `session` - a hash which allows you to access/modify/remove session variables
234
- (ex: `session[:foo] = 'bar'`)
235
- - `halt` - allows you to instantly return a response, interrupting current
236
- handler execution (see [halt][halt-definition])
237
-
238
- ## Filters
239
-
240
- Unlike Sinatra, NYNY supports only "generic" before and after filters.
241
- This means that you can't declare a filter to execute depending on a URL pattern.
242
- However, you can obtain the same effect by calling next in a before block
243
- if the request.path matches a pattern.
244
-
245
- ```ruby
246
- class App < NYNY::App
247
- before do
248
- next unless /html/ =~ request.path
249
- headers 'Content-Type' => 'text/html'
250
- end
251
-
252
- after do
253
- puts response.inspect
254
- end
255
-
256
- get '/' do
257
- 'hello'
258
- end
259
- end
260
- ```
261
-
262
- ## Middleware
263
-
264
- A NYNY app is a Rack middleware, which means that it can be used inside
265
- Sinatra, Rails, or any other Rack-based app:
266
-
267
- ```ruby
268
- class MyApp < Sinatra::Base
269
- use MyNYNYApp
270
- end
271
- ```
272
-
273
- NYNY also supports middleware itself, and that means you can use Rack middleware
274
- (or a Sinatra app) inside a NYNY app:
275
-
276
- ```ruby
277
- class App < NYNY::App
278
- # this will serve all the files in the "public" folder
279
- use Rack::Static :url => ['public']
280
- use SinatraApp
281
- end
282
- ```
283
-
284
- I recommend looking at [the list of Rack middlewares][rack-middleware]
285
-
286
- ## Helpers
287
-
288
- NYNY supports helpers as Sinatra does:
289
-
290
- ```ruby
291
- class App < NYNY::App
292
- helpers MyHelperModule
293
- helpers do
294
- def using_a_block_to_define_helper
295
- true
296
- end
297
- end
298
- end
299
- ```
300
-
301
-
302
- Using a helper implies that the helper module is included in the [RequestScope][2],
303
- and that all the methods in that module will be available inside a route
304
- definition block.
305
-
306
- ## Extensions
307
-
308
- Since version 2.0.0, NYNY added support for extensions.
309
- This makes possible to include helpers, middlewares and custom app class
310
- methods inside a single module:
311
-
312
- ```ruby
313
- module MyKewlExtension
314
- class Middleware
315
- def initialize app
316
- @app = app
317
- end
318
-
319
- def call env
320
- env['KEWL'] = true
321
- @app.call(env) if @app
322
- end
323
- end
324
-
325
- module Helpers
326
- def the_ultimate_answer
327
- 42
328
- end
329
- end
330
-
331
- def get_or_post route, &block
332
- get route, &block
333
- post route, &block
334
- end
335
-
336
- def self.registered app
337
- app.use Middleware
338
- app.helpers Helpers
339
-
340
- app.get_or_post '/' do
341
- "After many years of hard computation, the answer is #{the_ultimate_answer}"
342
- end
343
- end
344
- end
345
-
346
- class App < NYNY::App
347
- register MyKewlExtension
348
- end
349
-
350
- App.run!
351
- ```
352
-
353
- By default, the App class will `extend` the provided extension module.
354
- Optionally, an extension can add a `registered` method, which will be invoked
355
- once the extension is registered. That method will be called with the app class
356
- as a parameter.
357
-
358
- Since NYNY has the same extension interface as Sinatra, some Sinatra extensions
359
- might work with NYNY, although that is not guaranteed. However, an extension
360
- written for NYNY will always work with Sinatra. (Forward compatible)
361
-
362
- # F. A. Q.
363
- TBD.
364
-
365
- # Contributing
366
-
367
- 1. Fork it
368
- 2. Create your feature branch (`git checkout -b my-new-feature`)
369
- 3. Commit your changes (`git commit -am 'Add some feature'`)
370
- 4. Push to the branch (`git push origin my-new-feature`)
371
- 5. Create new Pull Request
372
-
373
- [0]: https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb
374
- [1]: https://github.com/sinatra/sinatra/pull/716
375
- [2]: https://github.com/alisnic/nyny/blob/master/lib/nyny/request_scope.rb
376
- [3]: http://rack.rubyforge.org/doc/classes/Rack/Request.html
377
- [4]: http://rack.rubyforge.org/doc/classes/Rack/Response.html
378
- [performance]: https://github.com/alisnic/nyny/blob/master/Performance.md
379
- [rack-middleware]: https://github.com/rack/rack/wiki/List-of-Middleware
380
- [halt-definition]: https://github.com/alisnic/nyny/blob/master/lib/nyny/request_scope.rb#L36
381
- [primitivesrb]: https://github.com/alisnic/nyny/blob/master/lib/nyny/primitives.rb
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