nyny 1.0.0.pre1

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 +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +5 -0
  7. data/LICENSE.txt +22 -0
  8. data/Performance.md +65 -0
  9. data/README.md +167 -0
  10. data/Rakefile +1 -0
  11. data/benchmarks/filters/frankie.rb +18 -0
  12. data/benchmarks/filters/sinatra.rb +17 -0
  13. data/benchmarks/helpers/frankie.rb +19 -0
  14. data/benchmarks/helpers/sinatra.rb +18 -0
  15. data/benchmarks/simple/frankie.rb +10 -0
  16. data/benchmarks/simple/sinatra.rb +9 -0
  17. data/benchmarks/url_pattern/frankie.rb +10 -0
  18. data/benchmarks/url_pattern/sinatra.rb +8 -0
  19. data/examples/active_record/.gitignore +1 -0
  20. data/examples/active_record/Gemfile +14 -0
  21. data/examples/active_record/Rakefile +51 -0
  22. data/examples/active_record/config/database.yml +0 -0
  23. data/examples/active_record/database.rb +12 -0
  24. data/examples/active_record/db/migrate/20130606133756_add_shouts.rb +12 -0
  25. data/examples/active_record/models/shout.rb +3 -0
  26. data/examples/active_record/server.rb +43 -0
  27. data/examples/json_api.rb +21 -0
  28. data/examples/templates/server.rb +27 -0
  29. data/examples/templates/views/index.haml +1 -0
  30. data/examples/web_sockets/public/FABridge.js +604 -0
  31. data/examples/web_sockets/public/WebSocketMain.swf +0 -0
  32. data/examples/web_sockets/public/index.html +76 -0
  33. data/examples/web_sockets/public/swfobject.js +4 -0
  34. data/examples/web_sockets/public/web_socket.js +388 -0
  35. data/examples/web_sockets/server.rb +60 -0
  36. data/lib/nyny.rb +9 -0
  37. data/lib/nyny/app.rb +66 -0
  38. data/lib/nyny/class_level_api.rb +40 -0
  39. data/lib/nyny/primitives.rb +25 -0
  40. data/lib/nyny/request_scope.rb +60 -0
  41. data/lib/nyny/route_signature.rb +44 -0
  42. data/lib/nyny/version.rb +3 -0
  43. data/nyny.gemspec +24 -0
  44. data/spec/app_spec.rb +144 -0
  45. data/spec/class_level_api_spec.rb +39 -0
  46. data/spec/primitives_spec.rb +26 -0
  47. data/spec/request_scope_spec.rb +71 -0
  48. data/spec/spec_helper.rb +42 -0
  49. metadata +138 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 46c8a11a01cebb1bd9a45524d3c05a66a3af2262
4
+ data.tar.gz: 67dd8bb1b90e4e11a273c0debe370fb40a00fd11
5
+ SHA512:
6
+ metadata.gz: 5542318ca155709ff482ebe99c3f1ab1896f5fa3183bcee856edd9e38ca581ad8e4b944ae1cb87876110bba084421c461f52aa9042da3e8e6e79c9f9fe48f85d
7
+ data.tar.gz: 55919c677098f054c192b508db71a92d60475590424815e74f8d33f3c6050181a74064b605707607e457f14683882250a9108f55ca1121470eb0c03c1780e653
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order rand
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ frankie
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rack'
data/LICENSE.txt ADDED
@@ -0,0 +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.
data/Performance.md ADDED
@@ -0,0 +1,65 @@
1
+ # Frankie vs Sinatra performance test
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`
5
+
6
+ Hardware: Intel(R) Core(TM) i7-2620M CPU @ 2.70GHz, 6 GB DDR3
7
+
8
+ ## Results
9
+
10
+ | Benchmark | Frankie (req/s) | Sinatra (req/s) |
11
+ |-----------|:---------------:|:---------------:|
12
+ | Simple |__5012__ |2534 |
13
+ | UrlPattern|__4564__ |2338 |
14
+ | Filters |__4510__ |2465 |
15
+ | Helpers |__4737__ |2663 |
16
+
17
+ See below the code for each benchmark
18
+
19
+ ## Code
20
+ ### Simple
21
+
22
+ class App < Frankie::App #(or Sinatra::Base)
23
+ get '/' do
24
+ 'Hello World!'
25
+ end
26
+ end
27
+
28
+ ### UrlPattern
29
+ class App < Frankie::App #(or Sinatra::Base)
30
+ get '/hello/:name' do
31
+ "Hello #{params[:name]}!"
32
+ end
33
+ end
34
+
35
+ ### Filters
36
+ class App < Frankie::App #(or Sinatra::Base)
37
+ before do
38
+ request
39
+ end
40
+
41
+ after do
42
+ response
43
+ end
44
+
45
+ get '/' do
46
+ 'Hello World!'
47
+ end
48
+ end
49
+
50
+ ### Helpers
51
+ module Dude
52
+ def da_request_man
53
+ request
54
+ end
55
+ end
56
+
57
+ class App < Frankie::App #(or Sinatra::Base)
58
+ helpers Dude
59
+
60
+ get '/' do
61
+ da_request_man
62
+ 'Hello World!'
63
+ end
64
+ end
65
+
data/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # New York, New York.
2
+ Sinatra's little brother.
3
+
4
+ - [TOP](#frankie)
5
+ - [Motivation](#motivation)
6
+ - [Philosophy](#philosophy)
7
+ - [Why use NYNY instead of Sinatra](#why-use-frankie-instead-of-sinatra)
8
+ - [Usage](#usage)
9
+ - [Running](#running)
10
+ - [Defining routes](#defining-routes)
11
+ - [Request scope](#request-scope)
12
+ - [Filters](#filters)
13
+ - [Middleware](#middleware)
14
+ - [Helpers](#helpers)
15
+ - [FAQ](#f-a-q)
16
+ - [Contributing](#contributing)
17
+
18
+ # Motivation
19
+ My efforts to write __NYNY__ started when I wanted to understand how __Sinatra__ works, and stumbled upon the [base.rb][0]. The majority of the classes that are used by sinatra are in one single file, which makes it nearly impossible for a new person to grasp.
20
+
21
+ [I've tried to change the situation][1], but unfortunately, my initiative was premature for the sinatra project (considering their plans).
22
+
23
+ I wanted to understand how sinatra works, but the code was pretty challenging. So I decided I should re-implement the basic things sinatra has. Thus, __NYNY__ was born.
24
+
25
+ # Philosophy
26
+ NYNY should have only the bare minimum to write basic web servers comfortably,
27
+ everything else should be in a extension (see frankie extensions). It is also
28
+ trivial to use frankie to build large and complex app, by writing multiple sub
29
+ apps and using Rack to mount them, or by using those sub apps in the "main" app
30
+ as middleware.
31
+
32
+ # Why use NYNY instead of Sinatra
33
+ - It's very small (~250 LOC), which is just a little overhead on top of Rack.
34
+ - Sinatra is a drop-in replacement for NYNY. Anytime you feel that you need more, you can just change your app to inherit from `Sinatra::Base`, your code will still work, and you will be able to use any of the Sinatra features.
35
+ - It's __~2 times faster__ than Sinatra (see [Performance][performance] for details)
36
+ - You want to dig into the source code and change to your needs (NYNY's source code is more welcoming)
37
+ - Each NYNY app is a Rack middleware, so it can be used inside of Sinatra, Rails, or any other Rack-based app.
38
+
39
+ # Usage
40
+
41
+ A NYNY app must _always_ be in a class which inherits from `NYNY::App`.
42
+
43
+ class App < NYNY::App
44
+ get '/' do
45
+ 'Hello, World'
46
+ end
47
+ end
48
+
49
+ ## Running
50
+ There are two ways to run a NYNY app __directly__ [[?]](#middleware):
51
+
52
+ - be requiring it in a `config.ru` file, and then passing it as argument to the
53
+ Rack's `run` function:
54
+
55
+ #config.ru
56
+ require 'app'
57
+ run App.new
58
+
59
+ - by using the `run!` method directly on the app class:
60
+
61
+ #app.rb
62
+ #...App class definition...
63
+
64
+ App.run!
65
+
66
+ `run!` takes the port number as optional argument (the default port is 9292). Also the `run!` method will include 2 default middlewares to make the development easier: Rack::CommonLogger and Rack::ShowExceptions. This will show all requests in the log, and will provide useful details in the case a error occurs during a request.
67
+
68
+
69
+ ## Defining routes
70
+
71
+ NYNY supports the following verbs for defining a route: delete, get, head, options, patch, post, put and trace.
72
+
73
+ class App < NYNY::App
74
+ post '/' do
75
+ 'You Posted, dude!'
76
+ end
77
+ end
78
+
79
+ NYNY also suports basic URL patterns:
80
+
81
+ class App < NYNY::App
82
+ get '/greet/:first_name/:last_name' do
83
+ # The last expression in the block is _always_ considered the response body.
84
+ "Hello #{params[:first_name]} #{params[:last_name]}!"
85
+ end
86
+ end
87
+
88
+ Each block that is passed to a route definition is evaluated in the context of a request scope. See below what methods are available there.
89
+
90
+ ## Request scope
91
+ As was said above, when you pass a block to a route definition, that block is evaluated in the context of a [RequestScope][2]. This means that several methods/objects available inside that block:
92
+
93
+ - `request` - A `Rack::Request` object which encapsulates the request to that route. (see [Rack::Request documentation][3] for more info)
94
+ - `params` - a hash which contains both POST body params and GET querystring params.
95
+ - `headers` - allows you to read/add headers to the response (ex: `headers 'Content-Type' => 'text/html'`)
96
+ - `status` - allows you to set the status of the response (ex: `status 403`)
97
+ - `redirect_to` - sets the response to redirect (ex: `redirect_to 'http://google.com'`)
98
+ - `cookies` - a hash which allows you to access/modify/remove cookies (ex: `cookies[:foo] = 'bar'`)
99
+ - `session` - a hash which allows you to access/modify/remove session variables (ex: `session[:foo] = 'bar'`)
100
+
101
+ ## Filters
102
+
103
+ Unlike Sinatra, NYNY supports only "generic" before and after filters. This means that you can't execute a filter depending on a URL pattern.
104
+
105
+ class App < NYNY::App
106
+ before do
107
+ headers 'Content-Type' => 'text/html'
108
+ end
109
+
110
+ after do
111
+ puts response.inspect
112
+ end
113
+
114
+ get '/' do
115
+ 'hello'
116
+ end
117
+ end
118
+
119
+ Before and after filters are also evaluated in a RequestScope context. A little exception are the after filters, which can access the __response__ object ([Rack::Response][4]).
120
+
121
+ ## Middleware
122
+
123
+ A Fankie app is a Rack middleware, which means that it can be used inside of Sinatra, Rails, or any other Rack-based app:
124
+
125
+ class MyApp < Sinatra::Base
126
+ use MyNYNYApp
127
+ end
128
+
129
+ NYNY also supports middleware itself, and that means you can use Rack middleware (or a Sinatra app) inside a NYNY app:
130
+
131
+ class App < NYNY::App
132
+ #this will serve all the files in the "public" folder
133
+ use Rack::Static :url => ['public']
134
+ use SinatraApp
135
+ end
136
+
137
+ I recommend looking at [the list of Rack middlewares][rack-middleware]
138
+
139
+ ## Helpers
140
+
141
+ NYNY supports helpers as Sinatra does:
142
+
143
+ class App < NYNY::App
144
+ helpers MyHelperModule
145
+ end
146
+
147
+ Using a helper implies that the helper module is included in the [RequestScope][2], and that all the methods in that module will be available inside a route definition block.
148
+
149
+ # F. A. Q.
150
+ TBD.
151
+
152
+
153
+ # Contributing
154
+
155
+ 1. Fork it
156
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
157
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
158
+ 4. Push to the branch (`git push origin my-new-feature`)
159
+ 5. Create new Pull Request
160
+
161
+ [0]: https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb
162
+ [1]: https://github.com/sinatra/sinatra/pull/716
163
+ [2]: https://github.com/alisnic/frankie/blob/master/lib/frankie/request_scope.rb
164
+ [3]: http://rack.rubyforge.org/doc/classes/Rack/Request.html
165
+ [4]: http://rack.rubyforge.org/doc/classes/Rack/Response.html
166
+ [performance]: https://github.com/alisnic/frankie/blob/master/Performance.md
167
+ [rack-middleware]: https://github.com/rack/rack/wiki/List-of-Middleware
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,18 @@
1
+ #!ruby -I ../../lib -I lib
2
+ require 'frankie'
3
+
4
+ class App < Frankie::App
5
+ before do
6
+ request
7
+ end
8
+
9
+ after do
10
+ response
11
+ end
12
+
13
+ get '/' do
14
+ 'Hello World!'
15
+ end
16
+ end
17
+
18
+ App.run!
@@ -0,0 +1,17 @@
1
+ #!ruby -I ../../lib -I lib
2
+ require 'sinatra'
3
+
4
+ class App < Sinatra::Base
5
+ before do
6
+ request
7
+ end
8
+
9
+ after do
10
+ response
11
+ end
12
+
13
+ get '/' do
14
+ 'Hello World!'
15
+ end
16
+ end
17
+
@@ -0,0 +1,19 @@
1
+ #!ruby -I ../../lib -I lib
2
+ require 'frankie'
3
+
4
+ module Dude
5
+ def da_request_man
6
+ request
7
+ end
8
+ end
9
+
10
+ class App < Frankie::App
11
+ helpers Dude
12
+
13
+ get '/' do
14
+ da_request_man
15
+ 'Hello World!'
16
+ end
17
+ end
18
+
19
+ App.run!
@@ -0,0 +1,18 @@
1
+ #!ruby -I ../../lib -I lib
2
+ require 'sinatra'
3
+
4
+ module Dude
5
+ def da_request_man
6
+ request
7
+ end
8
+ end
9
+
10
+ class App < Sinatra::Base
11
+ helpers Dude
12
+
13
+ get '/' do
14
+ da_request_man
15
+ 'Hello World!'
16
+ end
17
+ end
18
+
@@ -0,0 +1,10 @@
1
+ #!ruby -I ../../lib -I lib
2
+ require 'frankie'
3
+
4
+ class App < Frankie::App
5
+ get '/' do
6
+ 'Hello World!'
7
+ end
8
+ end
9
+
10
+ App.run!
@@ -0,0 +1,9 @@
1
+ #!ruby -I ../../lib -I lib
2
+ require 'sinatra'
3
+
4
+ class App < Sinatra::Base
5
+ get '/' do
6
+ 'Hello World!'
7
+ end
8
+ end
9
+
@@ -0,0 +1,10 @@
1
+ #!ruby -I ../../lib -I lib
2
+ require 'frankie'
3
+
4
+ class App < Frankie::App
5
+ get '/hello/:name' do
6
+ "Hello #{params[:name]}!"
7
+ end
8
+ end
9
+
10
+ App.run!
@@ -0,0 +1,8 @@
1
+ #!ruby -I ../../lib -I lib
2
+ require 'sinatra'
3
+
4
+ class App < Sinatra::Base
5
+ get '/hello/:name' do
6
+ "Hello #{params[:name]}!"
7
+ end
8
+ end
@@ -0,0 +1 @@
1
+ db/*.sqlite3
@@ -0,0 +1,14 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'activerecord', :require => 'active_record'
4
+ gem 'sqlite3'
5
+ gem 'rack'
6
+ gem 'thin'
7
+
8
+ group :development do
9
+ #
10
+ end
11
+
12
+ group :production do
13
+ #
14
+ end