nyny 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +20 -20
- data/.rspec +2 -2
- data/.ruby-version +1 -1
- data/.travis.yml +11 -11
- data/CHANGELOG +45 -40
- data/Gemfile +7 -8
- data/LICENSE.txt +22 -22
- data/Performance.md +41 -46
- data/README.md +423 -423
- data/Rakefile +6 -6
- data/benchmark.rb +116 -125
- data/lib/nyny.rb +33 -33
- data/lib/nyny/app.rb +79 -79
- data/lib/nyny/core-ext/runner.rb +19 -19
- data/lib/nyny/core-ext/templates.rb +20 -20
- data/lib/nyny/primitives.rb +25 -25
- data/lib/nyny/request_scope.rb +43 -43
- data/lib/nyny/route.rb +40 -40
- data/lib/nyny/router.rb +46 -44
- data/lib/nyny/version.rb +3 -3
- data/nyny.gemspec +29 -27
- data/spec/app_spec.rb +248 -248
- data/spec/inheritance_spec.rb +76 -75
- data/spec/nyny_spec.rb +11 -11
- data/spec/primitives_spec.rb +33 -33
- data/spec/request_scope_spec.rb +103 -103
- data/spec/router_spec.rb +29 -21
- data/spec/runner_spec.rb +23 -23
- data/spec/spec_helper.rb +61 -61
- data/spec/templates_spec.rb +52 -52
- data/spec/views/layout.erb +6 -6
- metadata +3 -3
data/lib/nyny/core-ext/runner.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
module NYNY
|
2
|
-
module Runner
|
3
|
-
def optimal_runner
|
4
|
-
return Rack::Handler::WEBrick if RUBY_PLATFORM == 'java'
|
5
|
-
|
6
|
-
begin
|
7
|
-
Rack::Handler::Thin
|
8
|
-
rescue LoadError
|
9
|
-
Rack::Handler::WEBrick
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def run! port=9292
|
14
|
-
use Rack::CommonLogger
|
15
|
-
use Rack::ShowExceptions unless NYNY.env.production?
|
16
|
-
optimal_runner.run new, :Port => port
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
1
|
+
module NYNY
|
2
|
+
module Runner
|
3
|
+
def optimal_runner
|
4
|
+
return Rack::Handler::WEBrick if RUBY_PLATFORM == 'java'
|
5
|
+
|
6
|
+
begin
|
7
|
+
Rack::Handler::Thin
|
8
|
+
rescue LoadError
|
9
|
+
Rack::Handler::WEBrick
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def run! port=9292
|
14
|
+
use Rack::CommonLogger
|
15
|
+
use Rack::ShowExceptions unless NYNY.env.production?
|
16
|
+
optimal_runner.run new, :Port => port
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,21 +1,21 @@
|
|
1
|
-
require 'tilt'
|
2
|
-
|
3
|
-
module NYNY
|
4
|
-
module Templates
|
5
|
-
module Helpers
|
6
|
-
def render template, locals = {}, options = {}, &block
|
7
|
-
template_cache.fetch(template) do
|
8
|
-
Tilt.new(template, options)
|
9
|
-
end.render(self, locals, &block)
|
10
|
-
end
|
11
|
-
|
12
|
-
def template_cache
|
13
|
-
Thread.current[:template_cache] ||= Tilt::Cache.new
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.registered app
|
18
|
-
app.helpers Helpers
|
19
|
-
end
|
20
|
-
end
|
1
|
+
require 'tilt'
|
2
|
+
|
3
|
+
module NYNY
|
4
|
+
module Templates
|
5
|
+
module Helpers
|
6
|
+
def render template, locals = {}, options = {}, &block
|
7
|
+
template_cache.fetch(template) do
|
8
|
+
Tilt.new(template, options)
|
9
|
+
end.render(self, locals, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def template_cache
|
13
|
+
Thread.current[:template_cache] ||= Tilt::Cache.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.registered app
|
18
|
+
app.helpers Helpers
|
19
|
+
end
|
20
|
+
end
|
21
21
|
end
|
data/lib/nyny/primitives.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
module NYNY
|
2
|
-
class Request < Rack::Request
|
3
|
-
end
|
4
|
-
|
5
|
-
class Response < Rack::Response
|
6
|
-
attr_reader :raw_body
|
7
|
-
|
8
|
-
def initialize body=[], status=200, header={}
|
9
|
-
@raw_body = body
|
10
|
-
super body.to_s, status, header
|
11
|
-
end
|
12
|
-
|
13
|
-
def body= value
|
14
|
-
@raw_body = value
|
15
|
-
@body = []
|
16
|
-
@length = 0
|
17
|
-
|
18
|
-
if value.respond_to? :to_str
|
19
|
-
write value.to_str
|
20
|
-
elsif value.respond_to?(:each)
|
21
|
-
value.each {|part| write part.to_s }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
1
|
+
module NYNY
|
2
|
+
class Request < Rack::Request
|
3
|
+
end
|
4
|
+
|
5
|
+
class Response < Rack::Response
|
6
|
+
attr_reader :raw_body
|
7
|
+
|
8
|
+
def initialize body=[], status=200, header={}
|
9
|
+
@raw_body = body
|
10
|
+
super body.to_s, status, header
|
11
|
+
end
|
12
|
+
|
13
|
+
def body= value
|
14
|
+
@raw_body = value
|
15
|
+
@body = []
|
16
|
+
@length = 0
|
17
|
+
|
18
|
+
if value.respond_to? :to_str
|
19
|
+
write value.to_str
|
20
|
+
elsif value.respond_to?(:each)
|
21
|
+
value.each {|part| write part.to_s }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/nyny/request_scope.rb
CHANGED
@@ -1,43 +1,43 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
require 'rack/contrib/cookies'
|
3
|
-
|
4
|
-
module NYNY
|
5
|
-
class RequestScope
|
6
|
-
extend Forwardable
|
7
|
-
|
8
|
-
attr_reader :request, :response
|
9
|
-
def_delegators :request, :params, :session
|
10
|
-
def_delegators :response, :headers
|
11
|
-
|
12
|
-
def initialize request
|
13
|
-
@request = request
|
14
|
-
@response = Response.new '', 200, {'Content-Type' => 'text/html'}
|
15
|
-
end
|
16
|
-
|
17
|
-
def cookies
|
18
|
-
@cookies ||= Rack::Cookies::CookieJar.new(request.cookies)
|
19
|
-
end
|
20
|
-
|
21
|
-
def status code
|
22
|
-
response.status = code
|
23
|
-
end
|
24
|
-
|
25
|
-
def halt status, headers={}, body=''
|
26
|
-
response.status = status
|
27
|
-
response.headers.merge! headers
|
28
|
-
response.body = body
|
29
|
-
throw :halt, response.finish
|
30
|
-
end
|
31
|
-
|
32
|
-
def redirect_to uri, status=302
|
33
|
-
halt status, {'Location' => uri}
|
34
|
-
end
|
35
|
-
alias_method :redirect, :redirect_to
|
36
|
-
|
37
|
-
def apply_to &handler
|
38
|
-
response.body = instance_eval(&handler)
|
39
|
-
cookies.finish!(response)
|
40
|
-
response.finish
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
1
|
+
require 'forwardable'
|
2
|
+
require 'rack/contrib/cookies'
|
3
|
+
|
4
|
+
module NYNY
|
5
|
+
class RequestScope
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
attr_reader :request, :response
|
9
|
+
def_delegators :request, :params, :session
|
10
|
+
def_delegators :response, :headers
|
11
|
+
|
12
|
+
def initialize request
|
13
|
+
@request = request
|
14
|
+
@response = Response.new '', 200, {'Content-Type' => 'text/html'}
|
15
|
+
end
|
16
|
+
|
17
|
+
def cookies
|
18
|
+
@cookies ||= Rack::Cookies::CookieJar.new(request.cookies)
|
19
|
+
end
|
20
|
+
|
21
|
+
def status code
|
22
|
+
response.status = code
|
23
|
+
end
|
24
|
+
|
25
|
+
def halt status, headers={}, body=''
|
26
|
+
response.status = status
|
27
|
+
response.headers.merge! headers
|
28
|
+
response.body = body
|
29
|
+
throw :halt, response.finish
|
30
|
+
end
|
31
|
+
|
32
|
+
def redirect_to uri, status=302
|
33
|
+
halt status, {'Location' => uri}
|
34
|
+
end
|
35
|
+
alias_method :redirect, :redirect_to
|
36
|
+
|
37
|
+
def apply_to &handler
|
38
|
+
response.body = instance_eval(&handler)
|
39
|
+
cookies.finish!(response)
|
40
|
+
response.finish
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/nyny/route.rb
CHANGED
@@ -1,40 +1,40 @@
|
|
1
|
-
module NYNY
|
2
|
-
class Route
|
3
|
-
NAME_PATTERN = /:(\S+)/
|
4
|
-
|
5
|
-
attr_reader :pattern, :handler, :method
|
6
|
-
def initialize method, signature, &block
|
7
|
-
@pattern = pattern_for signature
|
8
|
-
@handler = Proc.new(&block)
|
9
|
-
@method = method.to_s.upcase
|
10
|
-
end
|
11
|
-
|
12
|
-
def pattern_for signature
|
13
|
-
return signature if signature.is_a? Regexp
|
14
|
-
build_regex(signature.start_with?('/') ? signature : "/#{signature}")
|
15
|
-
end
|
16
|
-
|
17
|
-
def build_regex signature
|
18
|
-
return %r(^#{signature}$) unless signature.include?(':')
|
19
|
-
|
20
|
-
groups = signature.split('/').map do |part|
|
21
|
-
next part if part.empty?
|
22
|
-
next part unless part.start_with? ':'
|
23
|
-
name = NAME_PATTERN.match(part)[1]
|
24
|
-
%Q{(?<#{name}>\\S+)}
|
25
|
-
end.select {|s| !s.empty? }.join('\/')
|
26
|
-
|
27
|
-
%r(^\/#{groups}$)
|
28
|
-
end
|
29
|
-
|
30
|
-
def match? env
|
31
|
-
return false unless method == env['REQUEST_METHOD']
|
32
|
-
not pattern.match(env['PATH_INFO']).nil?
|
33
|
-
end
|
34
|
-
|
35
|
-
def url_params env
|
36
|
-
data = pattern.match(env['PATH_INFO'])
|
37
|
-
Hash[data.names.map {|n| [n.to_sym, URI.unescape(data[n])]}]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
1
|
+
module NYNY
|
2
|
+
class Route
|
3
|
+
NAME_PATTERN = /:(\S+)/
|
4
|
+
|
5
|
+
attr_reader :pattern, :handler, :method
|
6
|
+
def initialize method, signature, &block
|
7
|
+
@pattern = pattern_for signature
|
8
|
+
@handler = Proc.new(&block)
|
9
|
+
@method = method.to_s.upcase
|
10
|
+
end
|
11
|
+
|
12
|
+
def pattern_for signature
|
13
|
+
return signature if signature.is_a? Regexp
|
14
|
+
build_regex(signature.start_with?('/') ? signature : "/#{signature}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def build_regex signature
|
18
|
+
return %r(^#{signature}$) unless signature.include?(':')
|
19
|
+
|
20
|
+
groups = signature.split('/').map do |part|
|
21
|
+
next part if part.empty?
|
22
|
+
next part unless part.start_with? ':'
|
23
|
+
name = NAME_PATTERN.match(part)[1]
|
24
|
+
%Q{(?<#{name}>\\S+)}
|
25
|
+
end.select {|s| !s.empty? }.join('\/')
|
26
|
+
|
27
|
+
%r(^\/#{groups}$)
|
28
|
+
end
|
29
|
+
|
30
|
+
def match? env
|
31
|
+
return false unless method == env['REQUEST_METHOD']
|
32
|
+
not pattern.match(env['PATH_INFO']).nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def url_params env
|
36
|
+
data = pattern.match(env['PATH_INFO'])
|
37
|
+
Hash[data.names.map {|n| [n.to_sym, URI.unescape(data[n])]}]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/nyny/router.rb
CHANGED
@@ -1,44 +1,46 @@
|
|
1
|
-
module NYNY
|
2
|
-
class Router
|
3
|
-
attr_reader :fallback, :routes, :before_hooks, :after_hooks, :scope_class
|
4
|
-
def initialize options
|
5
|
-
@fallback = options[:fallback]
|
6
|
-
@routes = options[:routes]
|
7
|
-
@before_hooks = options[:before_hooks]
|
8
|
-
@after_hooks = options[:after_hooks]
|
9
|
-
@scope_class = options[:scope_class]
|
10
|
-
end
|
11
|
-
|
12
|
-
def call env
|
13
|
-
env['PATH_INFO'] = '/' if env['PATH_INFO'].empty?
|
14
|
-
route = routes.find {|route| route.match? env }
|
15
|
-
|
16
|
-
if route
|
17
|
-
process route, env
|
18
|
-
else
|
19
|
-
fallback.call env
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def process route, env
|
24
|
-
request = Request.new(env)
|
25
|
-
request.params.merge! route.url_params(env)
|
26
|
-
request.params.default_proc = proc {|h,k|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
1
|
+
module NYNY
|
2
|
+
class Router
|
3
|
+
attr_reader :fallback, :routes, :before_hooks, :after_hooks, :scope_class
|
4
|
+
def initialize options
|
5
|
+
@fallback = options[:fallback]
|
6
|
+
@routes = options[:routes]
|
7
|
+
@before_hooks = options[:before_hooks]
|
8
|
+
@after_hooks = options[:after_hooks]
|
9
|
+
@scope_class = options[:scope_class]
|
10
|
+
end
|
11
|
+
|
12
|
+
def call env
|
13
|
+
env['PATH_INFO'] = '/' if env['PATH_INFO'].empty?
|
14
|
+
route = routes.find {|route| route.match? env }
|
15
|
+
|
16
|
+
if route
|
17
|
+
process route, env
|
18
|
+
else
|
19
|
+
fallback.call env
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def process route, env
|
24
|
+
request = Request.new(env)
|
25
|
+
request.params.merge! route.url_params(env)
|
26
|
+
request.params.default_proc = proc { |h, k|
|
27
|
+
h.fetch(k.to_s, nil) || h.fetch(k.to_sym, nil)
|
28
|
+
}
|
29
|
+
|
30
|
+
eval_response scope_class.new(request), route.handler
|
31
|
+
end
|
32
|
+
|
33
|
+
def eval_response scope, handler
|
34
|
+
response = catch (:halt) do
|
35
|
+
before_hooks.each {|h| scope.instance_eval &h }
|
36
|
+
scope.apply_to &handler
|
37
|
+
end
|
38
|
+
|
39
|
+
catch (:halt) do
|
40
|
+
after_hooks.each {|h| scope.instance_eval &h }
|
41
|
+
end
|
42
|
+
|
43
|
+
response
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/nyny/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module NYNY
|
2
|
-
VERSION = "3.0.
|
3
|
-
end
|
1
|
+
module NYNY
|
2
|
+
VERSION = "3.0.1"
|
3
|
+
end
|
data/nyny.gemspec
CHANGED
@@ -1,27 +1,29 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'nyny/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.
|
8
|
-
|
9
|
-
spec.
|
10
|
-
spec.
|
11
|
-
spec.
|
12
|
-
spec.
|
13
|
-
spec.
|
14
|
-
spec.
|
15
|
-
|
16
|
-
spec.
|
17
|
-
|
18
|
-
spec.
|
19
|
-
spec.
|
20
|
-
|
21
|
-
spec.
|
22
|
-
|
23
|
-
spec.add_dependency "
|
24
|
-
spec.
|
25
|
-
spec.
|
26
|
-
spec.add_development_dependency "
|
27
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nyny/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.required_ruby_version = ">= 1.9.2"
|
8
|
+
|
9
|
+
spec.name = "nyny"
|
10
|
+
spec.version = NYNY::VERSION
|
11
|
+
spec.authors = ["Andrei Lisnic"]
|
12
|
+
spec.email = ["andrei.lisnic@gmail.com"]
|
13
|
+
spec.description = %q{New York, New York - (very) small Sinatra clone.}
|
14
|
+
spec.summary = %q{New York, New York.}
|
15
|
+
spec.homepage = "http://alisnic.github.io/nyny/"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files`.split($/).select {|f| !f.start_with?('examples')}
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "rack", "~> 1.5.2"
|
24
|
+
spec.add_dependency "rack-contrib", "~> 1.1.0"
|
25
|
+
spec.add_dependency "tilt", "~> 1.4.1"
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "rspec"
|
29
|
+
end
|