nyny 3.0.0 → 3.0.1
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 +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
|