nyny 2.2.1 → 3.0.0

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: 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