nyny 2.0.0 → 2.1.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +18 -3
  3. data/Performance.md +34 -63
  4. data/README.md +130 -76
  5. data/benchmark.rb +95 -0
  6. data/lib/nyny.rb +17 -1
  7. data/lib/nyny/app.rb +7 -3
  8. data/lib/nyny/core-ext/runner.rb +2 -1
  9. data/lib/nyny/{route_signature.rb → route.rb} +13 -8
  10. data/lib/nyny/router.rb +10 -18
  11. data/lib/nyny/version.rb +1 -1
  12. data/nyny.gemspec +1 -1
  13. data/spec/app_spec.rb +28 -3
  14. data/spec/nyny_spec.rb +11 -0
  15. data/spec/runner_spec.rb +6 -0
  16. data/spec/spec_helper.rb +1 -0
  17. metadata +6 -36
  18. data/benchmarks/filters/nyny.rb +0 -18
  19. data/benchmarks/filters/sinatra.rb +0 -17
  20. data/benchmarks/helpers/nyny.rb +0 -19
  21. data/benchmarks/helpers/sinatra.rb +0 -18
  22. data/benchmarks/simple/nyny.rb +0 -10
  23. data/benchmarks/simple/sinatra.rb +0 -9
  24. data/benchmarks/url_pattern/nyny.rb +0 -10
  25. data/benchmarks/url_pattern/sinatra.rb +0 -8
  26. data/examples/active_record/.gitignore +0 -1
  27. data/examples/active_record/Gemfile +0 -15
  28. data/examples/active_record/Rakefile +0 -51
  29. data/examples/active_record/config/database.yml +0 -0
  30. data/examples/active_record/database.rb +0 -13
  31. data/examples/active_record/db/migrate/20130606133756_add_shouts.rb +0 -12
  32. data/examples/active_record/models/shout.rb +0 -3
  33. data/examples/active_record/server.rb +0 -43
  34. data/examples/data_mapper/Gemfile +0 -7
  35. data/examples/data_mapper/database.rb +0 -7
  36. data/examples/data_mapper/db/.gitignore +0 -1
  37. data/examples/data_mapper/models/shout.rb +0 -7
  38. data/examples/data_mapper/server.rb +0 -41
  39. data/examples/json_api.rb +0 -21
  40. data/examples/templates/server.rb +0 -28
  41. data/examples/templates/views/index.haml +0 -1
  42. data/examples/web_sockets/Gemfile +0 -4
  43. data/examples/web_sockets/public/FABridge.js +0 -604
  44. data/examples/web_sockets/public/WebSocketMain.swf +0 -0
  45. data/examples/web_sockets/public/index.html +0 -76
  46. data/examples/web_sockets/public/swfobject.js +0 -4
  47. data/examples/web_sockets/public/web_socket.js +0 -388
  48. data/examples/web_sockets/server.rb +0 -60
  49. data/spec/route_signature_spec.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa8bdccd5f35a66eaa05e512117950e230350185
4
- data.tar.gz: 9932d345a2b696477bb9eef615671ce9db598de1
3
+ metadata.gz: bd3b0074fdefc837e7c08f4c760b894165bf2755
4
+ data.tar.gz: 4e7162b95bfbc2350f6f4cdccf36597ecf19ac8b
5
5
  SHA512:
6
- metadata.gz: 941652c537350c79204235b9d62af1dd7a55f0e2074a4c75043fad5f793c5ec87c1f85f6d02ec28d7df3286ac56270b1f2d7aaef07f272d5480ae6f13db3ea27
7
- data.tar.gz: a4a63feaf107bc95a0981f7b087c2a1e03d918bcf63fc1fbe23d3bf3e059a39b3124f3f8c5582fc03563deb4ca3866e3542f1803d6ca58186e03a36954aafb6f
6
+ metadata.gz: c3dc84c5a09a7dbb15ea47c52e55ff9679a473ad1241872fa81c44582ba0b3efe339f1cc1700a3dd29416191f221f58f2c926a0254cff08367dfcd50d5b59a8b
7
+ data.tar.gz: 963aac17eefd5aa6d1b67fdacddba1fb4bd0e91c14a104739921701307792968f8a4d5011f568ba12a900598e30e8386286babb6c468232c01cf1a3a84be6426
data/CHANGELOG CHANGED
@@ -1,9 +1,24 @@
1
+ 2.1.0
2
+ - Add ability to define helpers with a block
3
+ - Remove benchmark folder, and create a single benchmark file which can be
4
+ executed easily
5
+ - Simplified and optimized routing logic
6
+ - Fixed root path processing when a NYNY app is mounted
7
+ - Added Rails interop example
8
+ - Added session example
9
+ - Added NYNY.root
10
+ - Added NYNY.env
11
+ - NYNY will not show exceptions in production env
12
+
1
13
  2.0.0
2
14
  - Simplified and improved RouteSignature implementation
3
15
  - Simplified and improved RequestScope implementation
4
16
  - Made response object available in RequestScope
5
- - removed .use_protection! (the rack-protection) middleware can be easily
6
- used manually
7
- - add .register, which registers an extension (works the same way as in sinatra)
17
+ - removed .use_protection! (the rack-protection middleware can be easily
18
+ used manually)
19
+ - added support for extensions (using .register, which works the same way as in sinatra)
20
+
21
+ 1.0.2
22
+ - Add rack to runtime deps (@etehtsea)
8
23
 
9
24
  1.0.0 Initial release
@@ -1,73 +1,44 @@
1
- # NYNY vs Sinatra performance test
1
+ This output was generated by running benchmark.rb in repo root
2
2
 
3
- Note: all the tests below were made using Thin as a webserver. Httperf was
4
- choosen as the tool to do that. Bench settings: `--num-conns 10000`
3
+ Comparing NYNY 2.1.0 with Sinatra 1.4.3
5
4
 
6
- Hardware: Intel(R) Core(TM) i7-2620M CPU @ 2.70GHz, 6 GB DDR3
7
-
8
- If you have a clue how to make proper benchmarks (because, frankly, I don't), I am open to suggestions.
9
-
10
- ## Results
11
-
12
- | Benchmark | NYNY (req/s) | Sinatra (req/s) |
13
- |-----------|:---------------:|:---------------:|
14
- | Simple |__5012__ |2534 |
15
- | UrlPattern|__4564__ |2338 |
16
- | Filters |__4510__ |2465 |
17
- | Helpers |__4737__ |2663 |
18
-
19
- See below the code for each benchmark
20
-
21
- ## Code
22
- ### Simple
23
- ```ruby
24
- class App < NYNY::App #(or Sinatra::Base)
25
- get '/' do
26
- 'Hello World!'
27
- end
28
- end
5
+ Test: empty
29
6
  ```
30
-
31
- ### UrlPattern
32
- ```ruby
33
- class App < NYNY::App #(or Sinatra::Base)
34
- get '/hello/:name' do
35
- "Hello #{params[:name]}!"
36
- end
37
- end
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)
38
10
  ```
11
+ NYNY is **6.15x** faster than Sinatra in this test
39
12
 
40
- ### Filters
41
- ```ruby
42
- class App < NYNY::App #(or Sinatra::Base)
43
- before do
44
- request
45
- end
46
-
47
- after do
48
- response
49
- end
50
-
51
- get '/' do
52
- 'Hello World!'
53
- end
54
- end
13
+ Test: hello world
55
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
56
20
 
57
- ### Helpers
58
- ```ruby
59
- module Dude
60
- def da_request_man
61
- request
62
- end
63
- end
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
64
28
 
65
- class App < NYNY::App #(or Sinatra::Base)
66
- helpers Dude
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
67
36
 
68
- get '/' do
69
- da_request_man
70
- 'Hello World!'
71
- end
72
- end
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)
73
42
  ```
43
+ NYNY is **2.56x** faster than Sinatra in this test
44
+
data/README.md CHANGED
@@ -33,6 +33,7 @@ Open the browser at [http://localhost:9292](http://localhost:9292)
33
33
  - [Philosophy](#philosophy)
34
34
  - [Why use NYNY instead of Sinatra](#why-use-nyny-instead-of-sinatra)
35
35
  - [Usage](#usage)
36
+ - [Environment](#environment)
36
37
  - [Running](#running)
37
38
  - [Defining routes](#defining-routes)
38
39
  - [Request scope](#request-scope)
@@ -79,24 +80,55 @@ A NYNY app must _always_ be in a class which inherits from `NYNY::App`:
79
80
  end
80
81
  end
81
82
 
83
+ ## Environment
84
+ To get the directory in which your app is running use `NYNY.root`
85
+
86
+ ```ruby
87
+ #/some/folder/server.rb
88
+ require 'nyny'
89
+ puts NYNY.root #=> /some/folder/
90
+ ```
91
+
92
+ To get NYNY's environment, use `NYNY.env`
93
+
94
+ ```ruby
95
+ #env.rb
96
+ require 'nyny'
97
+ puts NYNY.env
98
+ puts NYNY.env.production?
99
+ ```
100
+
101
+ ```bash
102
+ $ ruby env.rb
103
+ development
104
+ false
105
+
106
+ $ ruby env.rb RACK_ENV=production
107
+ production
108
+ true
109
+ ```
110
+
82
111
  ## Running
83
112
  There are two ways to run a NYNY app __directly__ [[?]](#middleware):
84
113
 
85
114
  - by requiring it in a `config.ru` file, and then passing it as argument to the
86
115
  Rack's `run` function:
87
116
 
88
- # config.ru
89
-
90
- require 'app'
91
- run App.new
117
+ ```ruby
118
+ # config.ru
92
119
 
120
+ require 'app'
121
+ run App.new
122
+ ```
93
123
  - by using the `run!` method directly on the app class:
94
124
 
95
- # app.rb
96
-
97
- # ...app class definition...
125
+ ```ruby
126
+ # app.rb
127
+
128
+ # ...app class definition...
98
129
 
99
- App.run!
130
+ App.run!
131
+ ```
100
132
 
101
133
  `run!` takes the port number as optional argument (the default port is 9292).
102
134
  Also the `run!` method will include 2 default middlewares to make the
@@ -110,28 +142,34 @@ in the case a error occurs during a request.
110
142
  NYNY supports the following verbs for defining a route: delete, get, head,
111
143
  options, patch, post, put and trace.
112
144
 
113
- class App < NYNY::App
114
- post '/' do
115
- 'You Posted, dude!'
116
- end
117
- end
145
+ ```ruby
146
+ class App < NYNY::App
147
+ post '/' do
148
+ 'You Posted, dude!'
149
+ end
150
+ end
151
+ ```
118
152
 
119
153
  NYNY also suports basic URL patterns:
120
154
 
121
- class App < NYNY::App
122
- get '/greet/:first_name/:last_name' do
123
- # the last expression in the block is _always_ considered the response body.
124
- "Hello #{params[:first_name]} #{params[:last_name]}!"
125
- end
126
- end
155
+ ```ruby
156
+ class App < NYNY::App
157
+ get '/greet/:first_name/:last_name' do
158
+ # the last expression in the block is _always_ considered the response body.
159
+ "Hello #{params[:first_name]} #{params[:last_name]}!"
160
+ end
161
+ end
162
+ ```
127
163
 
128
164
  you can also tell NYNY to match a regex for a path:
129
165
 
130
- class App < NYNY::App
131
- get /html/ do
132
- 'Your URL contains html!'
133
- end
134
- end
166
+ ```ruby
167
+ class App < NYNY::App
168
+ get /html/ do
169
+ 'Your URL contains html!'
170
+ end
171
+ end
172
+ ```
135
173
 
136
174
  Each block that is passed to a route definition is evaluated in the context of
137
175
  a request scope. See below what methods are available there.
@@ -164,38 +202,44 @@ This means that you can't declare a filter to execute depending on a URL pattern
164
202
  However, you can obtain the same effect by calling next in a before block
165
203
  if the request.path matches a pattern.
166
204
 
167
- class App < NYNY::App
168
- before do
169
- next unless /html/ =~ request.path
170
- headers 'Content-Type' => 'text/html'
171
- end
205
+ ```ruby
206
+ class App < NYNY::App
207
+ before do
208
+ next unless /html/ =~ request.path
209
+ headers 'Content-Type' => 'text/html'
210
+ end
172
211
 
173
- after do
174
- puts response.inspect
175
- end
212
+ after do
213
+ puts response.inspect
214
+ end
176
215
 
177
- get '/' do
178
- 'hello'
179
- end
180
- end
216
+ get '/' do
217
+ 'hello'
218
+ end
219
+ end
220
+ ```
181
221
 
182
222
  ## Middleware
183
223
 
184
224
  A NYNY app is a Rack middleware, which means that it can be used inside
185
225
  Sinatra, Rails, or any other Rack-based app:
186
226
 
187
- class MyApp < Sinatra::Base
188
- use MyNYNYApp
189
- end
227
+ ```ruby
228
+ class MyApp < Sinatra::Base
229
+ use MyNYNYApp
230
+ end
231
+ ```
190
232
 
191
233
  NYNY also supports middleware itself, and that means you can use Rack middleware
192
234
  (or a Sinatra app) inside a NYNY app:
193
235
 
194
- class App < NYNY::App
195
- # this will serve all the files in the "public" folder
196
- use Rack::Static :url => ['public']
197
- use SinatraApp
198
- end
236
+ ```ruby
237
+ class App < NYNY::App
238
+ # this will serve all the files in the "public" folder
239
+ use Rack::Static :url => ['public']
240
+ use SinatraApp
241
+ end
242
+ ```
199
243
 
200
244
  I recommend looking at [the list of Rack middlewares][rack-middleware]
201
245
 
@@ -203,9 +247,17 @@ I recommend looking at [the list of Rack middlewares][rack-middleware]
203
247
 
204
248
  NYNY supports helpers as Sinatra does:
205
249
 
206
- class App < NYNY::App
207
- helpers MyHelperModule
250
+ ```ruby
251
+ class App < NYNY::App
252
+ helpers MyHelperModule
253
+ helpers do
254
+ def using_a_block_to_define_helper
255
+ true
208
256
  end
257
+ end
258
+ end
259
+ ```
260
+
209
261
 
210
262
  Using a helper implies that the helper module is included in the [RequestScope][2],
211
263
  and that all the methods in that module will be available inside a route
@@ -217,44 +269,46 @@ Since version 2.0.0, NYNY added support for extensions.
217
269
  This makes possible to include helpers, middlewares and custom app class
218
270
  methods inside a single module:
219
271
 
220
- module MyKewlExtension
221
- class Middleware
222
- def initialize app
223
- @app = app
224
- end
272
+ ```ruby
273
+ module MyKewlExtension
274
+ class Middleware
275
+ def initialize app
276
+ @app = app
277
+ end
225
278
 
226
- def call env
227
- env['KEWL'] = true
228
- @app.call(env) if @app
229
- end
230
- end
279
+ def call env
280
+ env['KEWL'] = true
281
+ @app.call(env) if @app
282
+ end
283
+ end
231
284
 
232
- module Helpers
233
- def the_ultimate_answer
234
- 42
235
- end
236
- end
285
+ module Helpers
286
+ def the_ultimate_answer
287
+ 42
288
+ end
289
+ end
237
290
 
238
- def get_or_post route, &block
239
- get route, &block
240
- post route, &block
241
- end
291
+ def get_or_post route, &block
292
+ get route, &block
293
+ post route, &block
294
+ end
242
295
 
243
- def self.registered app
244
- app.use Middleware
245
- app.helpers Helpers
296
+ def self.registered app
297
+ app.use Middleware
298
+ app.helpers Helpers
246
299
 
247
- app.get_or_post '/' do
248
- "After many years of hard computation, the answer is #{the_ultimate_answer}"
249
- end
250
- end
300
+ app.get_or_post '/' do
301
+ "After many years of hard computation, the answer is #{the_ultimate_answer}"
251
302
  end
303
+ end
304
+ end
252
305
 
253
- class App < NYNY::App
254
- register MyKewlExtension
255
- end
306
+ class App < NYNY::App
307
+ register MyKewlExtension
308
+ end
256
309
 
257
- App.run!
310
+ App.run!
311
+ ```
258
312
 
259
313
  By default, the App class will `extend` the provided extension module.
260
314
  Optionally, an extension can add a `registered` method, which will be invoked
@@ -0,0 +1,95 @@
1
+ #!ruby -I ./lib -I lib
2
+ require 'nyny'
3
+ require 'ruby-prof'
4
+ require 'benchmark'
5
+ require 'sinatra'
6
+ include Benchmark
7
+
8
+ set :run, false #do not run sinatra's builtin web server
9
+
10
+ def build_apps &block
11
+ sinatra = Class.new(Sinatra::Base, &block).new
12
+ nyny = Class.new(NYNY::App, &block).new
13
+ return [nyny, sinatra].map {|app| Rack::MockRequest.new(app) }
14
+ end
15
+
16
+ def run_test name, apps, &block
17
+ nyny, sinatra = apps
18
+ prc = Proc.new(&block)
19
+
20
+ puts "\nTest: #{name}"
21
+ Benchmark.benchmark(CAPTION, 7, FORMAT, "> NYNY/Sinatra:") do |x|
22
+ nyny_time = x.report("nyny: ") { 1000.times { prc.call(nyny) } }
23
+ sinatra_time = x.report("sinatra:") { 1000.times { prc.call(sinatra) } }
24
+ puts "NYNY is #{"%.2f" % [sinatra_time.real/nyny_time.real]}x faster than Sinatra in this test"
25
+ end
26
+ end
27
+
28
+ puts "Comparing NYNY #{NYNY::VERSION} with Sinatra #{Sinatra::VERSION}"
29
+
30
+ #
31
+ # Empty app
32
+ apps = build_apps do
33
+ #empty app
34
+ end
35
+ run_test 'empty', apps do |app|
36
+ app.get '/'
37
+ end
38
+
39
+ #
40
+ # Hello World
41
+ apps = build_apps do
42
+ get '/' do
43
+ 'Hello World'
44
+ end
45
+ end
46
+ run_test 'hello world', apps do |app|
47
+ app.get '/'
48
+ end
49
+
50
+ #
51
+ # Filters
52
+ apps = build_apps do
53
+ before do
54
+ request
55
+ end
56
+
57
+ after do
58
+ response
59
+ end
60
+
61
+ get '/' do
62
+ 'Hello World!'
63
+ end
64
+ end
65
+ run_test 'filters', apps do |app|
66
+ app.get '/'
67
+ end
68
+
69
+ #
70
+ # Helpers
71
+ apps = build_apps do
72
+ helpers do
73
+ def da_request
74
+ request
75
+ end
76
+ end
77
+
78
+ get '/' do
79
+ da_request
80
+ end
81
+ end
82
+ run_test 'helpers', apps do |app|
83
+ app.get '/'
84
+ end
85
+
86
+ #
87
+ # Url patterns
88
+ apps = build_apps do
89
+ get '/:name' do
90
+ params[:name]
91
+ end
92
+ end
93
+ run_test 'Url patterns', apps do |app|
94
+ app.get '/foo'
95
+ end