usher 0.7.2 → 0.7.3
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.
- data/benchmarks/generation_bm.rb +1 -0
- data/lib/usher.rb +6 -11
- data/lib/usher/node.rb +3 -0
- data/lib/usher/node/root.rb +4 -0
- data/lib/usher/node/root_ignoring_trailing_delimiters.rb +24 -0
- data/lib/usher/route/path.rb +71 -1
- data/lib/usher/route/variable.rb +12 -0
- data/lib/usher/util/generate.rb +2 -46
- data/spec/private/sinatra/recognize_spec.rb +38 -0
- data/usher.gemspec +1 -1
- metadata +4 -3
data/benchmarks/generation_bm.rb
CHANGED
data/lib/usher.rb
CHANGED
@@ -51,7 +51,7 @@ class Usher
|
|
51
51
|
# set.reset!
|
52
52
|
# set.empty? => true
|
53
53
|
def reset!
|
54
|
-
@root =
|
54
|
+
@root = class_for_root.new(self, request_methods)
|
55
55
|
@named_routes = {}
|
56
56
|
@routes = []
|
57
57
|
@grapher = Grapher.new(self)
|
@@ -254,16 +254,7 @@ class Usher
|
|
254
254
|
# route = set.add_route('/test')
|
255
255
|
# set.recognize(Request.new('/test')).path.route == route => true
|
256
256
|
def recognize(request, path = request.path)
|
257
|
-
|
258
|
-
path_size = path.size
|
259
|
-
path = path.gsub(/#{Regexp.quote(delimiters.first)}$/, '')
|
260
|
-
response = root.find(request, path, splitter.split(path))
|
261
|
-
response.only_trailing_delimiters = (path.size != path_size) if response
|
262
|
-
response
|
263
|
-
else
|
264
|
-
root.find(request, path, splitter.split(path))
|
265
|
-
end
|
266
|
-
|
257
|
+
root.lookup(request, path)
|
267
258
|
end
|
268
259
|
|
269
260
|
# Recognizes a `path`
|
@@ -396,4 +387,8 @@ class Usher
|
|
396
387
|
routes.each{|r| grapher.add_route(r)}
|
397
388
|
end
|
398
389
|
|
390
|
+
def class_for_root
|
391
|
+
ignore_trailing_delimiters? ? Node::RootIgnoringTrailingDelimiters : Node::Root
|
392
|
+
end
|
393
|
+
|
399
394
|
end
|
data/lib/usher/node.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.join('usher', 'node', 'root')
|
2
|
+
require File.join('usher', 'node', 'root_ignoring_trailing_delimiters')
|
2
3
|
require File.join('usher', 'node', 'response')
|
3
4
|
|
4
5
|
class Usher
|
@@ -51,6 +52,8 @@ class Usher
|
|
51
52
|
out
|
52
53
|
end
|
53
54
|
|
55
|
+
protected
|
56
|
+
|
54
57
|
def find(request_object, original_path, path, params = [])
|
55
58
|
# terminates or is partial
|
56
59
|
|
data/lib/usher/node/root.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
class Usher
|
2
|
+
class Node
|
3
|
+
class RootIgnoringTrailingDelimiters < Root
|
4
|
+
|
5
|
+
alias_method :lookup_without_stripping, :lookup
|
6
|
+
|
7
|
+
def initialize(route_set, request_methods)
|
8
|
+
super
|
9
|
+
@stripper = /#{Regexp.quote(route_set.delimiters.first)}$/
|
10
|
+
end
|
11
|
+
|
12
|
+
def lookup(request_object, path)
|
13
|
+
if path.size > 1
|
14
|
+
new_path = path.gsub(@stripper, '')
|
15
|
+
response = lookup_without_stripping(request_object, new_path)
|
16
|
+
response.only_trailing_delimiters = (new_path.size != path.size) if response
|
17
|
+
response
|
18
|
+
else
|
19
|
+
lookup_without_stripping(request_object, path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/usher/route/path.rb
CHANGED
@@ -8,6 +8,7 @@ class Usher
|
|
8
8
|
def initialize(route, parts)
|
9
9
|
self.route = route
|
10
10
|
self.parts = parts
|
11
|
+
build_generator
|
11
12
|
end
|
12
13
|
|
13
14
|
def convert_params_array(ary)
|
@@ -64,12 +65,81 @@ class Usher
|
|
64
65
|
Path.new(route, new_parts)
|
65
66
|
end
|
66
67
|
|
68
|
+
def generate
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def generate_from_hash(params = nil)
|
73
|
+
generate
|
74
|
+
end
|
75
|
+
|
67
76
|
private
|
68
77
|
def parts=(parts)
|
69
78
|
@parts = parts
|
70
79
|
@dynamic = @parts && @parts.any?{|p| p.is_a?(Variable)}
|
71
80
|
end
|
72
|
-
|
81
|
+
|
82
|
+
def build_generator
|
83
|
+
if parts
|
84
|
+
interpolating_path = ''
|
85
|
+
|
86
|
+
parts.each_with_index do |part, index|
|
87
|
+
case part
|
88
|
+
when String
|
89
|
+
interpolating_path << part
|
90
|
+
when Static::Greedy
|
91
|
+
interpolating_path << part.generate_with
|
92
|
+
when Variable::Glob
|
93
|
+
interpolating_path << '#{('
|
94
|
+
interpolating_path << "Array(arg#{index})"
|
95
|
+
if part.default_value
|
96
|
+
interpolating_path << ' || '
|
97
|
+
interpolating_path << part.default_value.inspect
|
98
|
+
end
|
99
|
+
interpolating_path << ').join(route.router.delimiters.first)}'
|
100
|
+
when Variable
|
101
|
+
interpolating_path << '#{'
|
102
|
+
interpolating_path << "arg#{index}"
|
103
|
+
if part.default_value
|
104
|
+
interpolating_path << ' || '
|
105
|
+
interpolating_path << part.default_value.inspect
|
106
|
+
end
|
107
|
+
interpolating_path << '}'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
generating_method = "def generate"
|
112
|
+
if dynamic?
|
113
|
+
generating_method << "("
|
114
|
+
generating_method << dynamic_indicies.map{|di| "arg#{di}"}.join(", ")
|
115
|
+
generating_method << ")\n"
|
116
|
+
dynamic_indicies.each do |di|
|
117
|
+
dp = parts.at(di)
|
118
|
+
generating_method << "@parts.at(#{di}).valid!(arg#{di})\n" if dp.validates?
|
119
|
+
end
|
120
|
+
else
|
121
|
+
generating_method << "\n"
|
122
|
+
end
|
123
|
+
|
124
|
+
generating_method << '"'
|
125
|
+
generating_method << interpolating_path
|
126
|
+
generating_method << '"'
|
127
|
+
generating_method << "\nend\n\n"
|
128
|
+
generating_method << "def generate_from_hash(params = nil)\n"
|
129
|
+
generating_method << "generate("
|
130
|
+
if parts && dynamic?
|
131
|
+
generating_method << dynamic_indicies.map { |di|
|
132
|
+
dp = parts.at(di)
|
133
|
+
arg = "params && params.delete(:#{dp.name}) "
|
134
|
+
arg << "|| @parts.at(#{di}).default_value " if dp.default_value
|
135
|
+
arg << "|| raise(MissingParameterException.new(\"expected a value for #{dp.name}\"))"
|
136
|
+
}.join(', ')
|
137
|
+
end
|
138
|
+
generating_method << ")\nend\n\n"
|
139
|
+
instance_eval generating_method
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
73
143
|
end
|
74
144
|
end
|
75
145
|
end
|
data/lib/usher/route/variable.rb
CHANGED
@@ -2,7 +2,14 @@ class Usher
|
|
2
2
|
class Route
|
3
3
|
class Variable
|
4
4
|
|
5
|
+
module Validator
|
6
|
+
def validates?
|
7
|
+
true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
5
11
|
module ProcValidator
|
12
|
+
include Validator
|
6
13
|
def valid!(val)
|
7
14
|
begin
|
8
15
|
@validator.call(val)
|
@@ -13,6 +20,7 @@ class Usher
|
|
13
20
|
end
|
14
21
|
|
15
22
|
module CaseEqualsValidator
|
23
|
+
include Validator
|
16
24
|
def valid!(val)
|
17
25
|
@validator === val.to_s or raise(ValidationException.new("#{val} does not conform to #{@validator}"))
|
18
26
|
end
|
@@ -40,6 +48,10 @@ class Usher
|
|
40
48
|
def valid!(val)
|
41
49
|
end
|
42
50
|
|
51
|
+
def validates?
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
43
55
|
def ==(o)
|
44
56
|
o && (o.class == self.class && o.name == @name && o.validator == @validator)
|
45
57
|
end
|
data/lib/usher/util/generate.rb
CHANGED
@@ -21,55 +21,11 @@ class Usher
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def generate_path_for_base_params_with_hash(path, params)
|
24
|
-
|
25
|
-
path.parts.each do |part|
|
26
|
-
case part
|
27
|
-
when String
|
28
|
-
result << part
|
29
|
-
when Route::Variable::Glob
|
30
|
-
value = (params && params.delete(part.name)) || part.default_value || raise(MissingParameterException.new("expected a value for #{part.name}"))
|
31
|
-
value.each_with_index do |current_value, index|
|
32
|
-
part.valid!(current_value)
|
33
|
-
result << current_value.to_s
|
34
|
-
result << usher.delimiters.first if index != value.size - 1
|
35
|
-
end
|
36
|
-
when Route::Variable
|
37
|
-
value = (params && params.delete(part.name)) || part.default_value || raise(MissingParameterException.new("expected a value for #{part.name}"))
|
38
|
-
part.valid!(value)
|
39
|
-
result << value.to_s
|
40
|
-
when Route::Static::Greedy
|
41
|
-
result << part.generate_with
|
42
|
-
else
|
43
|
-
raise
|
44
|
-
end
|
45
|
-
end
|
46
|
-
result
|
24
|
+
path.generate_from_hash(params)
|
47
25
|
end
|
48
26
|
|
49
27
|
def generate_path_for_base_params_with_array(path, params)
|
50
|
-
|
51
|
-
path.parts.each do |part|
|
52
|
-
case part
|
53
|
-
when String
|
54
|
-
result << part
|
55
|
-
when Route::Variable::Glob
|
56
|
-
value = (params && params.shift) || part.default_value || raise(MissingParameterException.new)
|
57
|
-
value.each_with_index do |current_value, index|
|
58
|
-
part.valid!(current_value)
|
59
|
-
result << current_value.to_s
|
60
|
-
result << usher.delimiters.first if index != value.size - 1
|
61
|
-
end
|
62
|
-
when Route::Variable
|
63
|
-
value = (params && params.shift) || part.default_value || raise(MissingParameterException.new)
|
64
|
-
part.valid!(value)
|
65
|
-
result << value.to_s
|
66
|
-
when Route::Static::Greedy
|
67
|
-
result << value.generate_with
|
68
|
-
else
|
69
|
-
raise
|
70
|
-
end
|
71
|
-
end
|
72
|
-
result
|
28
|
+
path.generate(*params.slice!(0, path.dynamic_parts.size))
|
73
29
|
end
|
74
30
|
|
75
31
|
end
|
@@ -49,6 +49,23 @@ describe "Usher (for Sinatra) route recognition" do
|
|
49
49
|
response.body.should == "bar"
|
50
50
|
end
|
51
51
|
|
52
|
+
it "should ignore trailing delimiters with an optional param" do
|
53
|
+
@app.get("/foo/(:bar)") { params[:bar] }
|
54
|
+
@app.get("/bar(/:foo)") { params[:foo] }
|
55
|
+
response = @app.call_with_mock_request('/foo/bar')
|
56
|
+
response.status.should == 200
|
57
|
+
response.body.should == "bar"
|
58
|
+
response = @app.call_with_mock_request('/bar/foo')
|
59
|
+
response.status.should == 200
|
60
|
+
response.body.should == "foo"
|
61
|
+
response = @app.call_with_mock_request('/bar')
|
62
|
+
response.status.should == 200
|
63
|
+
response.body.should == ""
|
64
|
+
response = @app.call_with_mock_request('/bar/')
|
65
|
+
response.status.should == 200
|
66
|
+
response.body.should == ""
|
67
|
+
end
|
68
|
+
|
52
69
|
it "should use sinatra optionals trailing delimiters" do
|
53
70
|
@app.get("/foo/?") { "foo" }
|
54
71
|
response = @app.call_with_mock_request('/foo')
|
@@ -99,4 +116,25 @@ describe "Usher (for Sinatra) route recognition" do
|
|
99
116
|
response.body.should_not match(/__sinatra__/)
|
100
117
|
end
|
101
118
|
end
|
119
|
+
|
120
|
+
describe "recognize paths" do
|
121
|
+
|
122
|
+
it "should recognize basic routes" do
|
123
|
+
pending "undefined method `request_method' for nil:NilClass"
|
124
|
+
@app.get("/foo/:bar") { "foo" }
|
125
|
+
@app.router.recognize_path("/foo/:bar").should == nil
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "priority" do
|
130
|
+
|
131
|
+
it "should set correctly priorities" do
|
132
|
+
pending "match the wrong route"
|
133
|
+
@app.get("/:id/:right", :priority => 10) { "right" }
|
134
|
+
@app.get("/:id/:wrong") { "wrong" }
|
135
|
+
response = @app.call_with_mock_request('/foo/bar')
|
136
|
+
response.status.should == 200
|
137
|
+
response.body.should == "right"
|
138
|
+
end
|
139
|
+
end
|
102
140
|
end
|
data/usher.gemspec
CHANGED
@@ -5,7 +5,7 @@ require "base64"
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "usher"
|
8
|
-
s.version = "0.7.
|
8
|
+
s.version = "0.7.3"
|
9
9
|
s.authors = ["Daniel Neighman", "Daniel Vartanov", "Jakub Šťastný", "Joshua Hull"]
|
10
10
|
s.homepage = "http://github.com/joshbuddy/usher"
|
11
11
|
s.summary = "Pure ruby general purpose router with interfaces for rails, rack, email or choose your own adventure"
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 7
|
8
|
-
-
|
9
|
-
version: 0.7.
|
8
|
+
- 3
|
9
|
+
version: 0.7.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Daniel Neighman
|
@@ -18,7 +18,7 @@ authors:
|
|
18
18
|
autorequire:
|
19
19
|
bindir: bin
|
20
20
|
cert_chain:
|
21
|
-
date: 2010-
|
21
|
+
date: 2010-05-02 00:00:00 -04:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -124,6 +124,7 @@ files:
|
|
124
124
|
- lib/usher/node.rb
|
125
125
|
- lib/usher/node/response.rb
|
126
126
|
- lib/usher/node/root.rb
|
127
|
+
- lib/usher/node/root_ignoring_trailing_delimiters.rb
|
127
128
|
- lib/usher/route.rb
|
128
129
|
- lib/usher/route/path.rb
|
129
130
|
- lib/usher/route/request_method.rb
|