joshbuddy-usher 0.3.2 → 0.3.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/Rakefile +7 -0
- data/VERSION.yml +2 -2
- data/lib/usher.rb +6 -6
- data/lib/usher/node.rb +7 -33
- data/lib/usher/route/request_method.rb +2 -1
- data/spec/generate_spec.rb +9 -0
- data/spec/grapher_spec.rb +5 -0
- data/spec/path_spec.rb +29 -0
- data/spec/recognize_spec.rb +20 -0
- data/spec/request_method_spec.rb +15 -0
- data/spec/split_spec.rb +10 -0
- metadata +3 -2
data/Rakefile
CHANGED
data/VERSION.yml
CHANGED
data/lib/usher.rb
CHANGED
@@ -44,10 +44,10 @@ class Usher
|
|
44
44
|
# The +request_methods+ are methods that are called against the request object in order to
|
45
45
|
# enforce the +conditions+ segment of the routes. For HTTP routes (and in fact the default), those
|
46
46
|
# methods are <tt>[:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method]</tt>.
|
47
|
-
def initialize(
|
48
|
-
@delimiters =
|
49
|
-
@
|
50
|
-
@
|
47
|
+
def initialize(options = {})
|
48
|
+
@delimiters = options.delete(:options) || ['/', '.']
|
49
|
+
@request_methods = options.delete(:request_methods) || [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains]
|
50
|
+
@splitter = Splitter.for_delimiters(@delimiters)
|
51
51
|
reset!
|
52
52
|
end
|
53
53
|
|
@@ -117,7 +117,7 @@ class Usher
|
|
117
117
|
conditions = options.delete(:conditions) || {}
|
118
118
|
requirements = options.delete(:requirements) || {}
|
119
119
|
options.delete_if do |k, v|
|
120
|
-
if v.is_a?(Regexp)
|
120
|
+
if v.is_a?(Regexp) || v.is_a?(Proc)
|
121
121
|
requirements[k] = v
|
122
122
|
true
|
123
123
|
end
|
@@ -173,7 +173,7 @@ class Usher
|
|
173
173
|
else
|
174
174
|
route
|
175
175
|
end
|
176
|
-
|
176
|
+
raise UnrecognizedException.new unless path
|
177
177
|
params_hash = {}
|
178
178
|
param_list = case params
|
179
179
|
when Hash
|
data/lib/usher/node.rb
CHANGED
@@ -16,7 +16,6 @@ class Usher
|
|
16
16
|
@value = value
|
17
17
|
@lookup = FuzzyHash.new
|
18
18
|
@exclusive_type = nil
|
19
|
-
@has_globber = find_parent{|p| p.value && p.value.is_a?(Route::Variable)}
|
20
19
|
end
|
21
20
|
|
22
21
|
def depth
|
@@ -29,28 +28,10 @@ class Usher
|
|
29
28
|
root
|
30
29
|
end
|
31
30
|
|
32
|
-
def has_globber?
|
33
|
-
@has_globber
|
34
|
-
end
|
35
|
-
|
36
31
|
def terminates?
|
37
32
|
@terminates
|
38
33
|
end
|
39
34
|
|
40
|
-
def find_parent(&blk)
|
41
|
-
if @parent.nil? || !@parent.is_a?(Node)
|
42
|
-
nil
|
43
|
-
elsif yield @parent
|
44
|
-
@parent
|
45
|
-
else #keep searching
|
46
|
-
@parent.find_parent(&blk)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def replace(src, dest)
|
51
|
-
@lookup.replace(src, dest)
|
52
|
-
end
|
53
|
-
|
54
35
|
def pp
|
55
36
|
$stdout << " " * depth
|
56
37
|
$stdout << "#{depth}: #{value.inspect} #{!!terminates?}\n"
|
@@ -83,12 +64,7 @@ class Usher
|
|
83
64
|
current_node.lookup[nil] ||= Node.new(current_node, Route::RequestMethod.new(current_node.exclusive_type, nil))
|
84
65
|
end
|
85
66
|
else
|
86
|
-
|
87
|
-
parts.unshift(key)
|
88
|
-
current_node.lookup[nil] ||= Node.new(current_node, Route::RequestMethod.new(current_node.exclusive_type, nil))
|
89
|
-
else
|
90
|
-
current_node.lookup[key.is_a?(Route::Variable) ? nil : key] ||= Node.new(current_node, key)
|
91
|
-
end
|
67
|
+
current_node.lookup[key.is_a?(Route::Variable) ? nil : key] ||= Node.new(current_node, key)
|
92
68
|
end
|
93
69
|
current_node = target_node
|
94
70
|
end
|
@@ -109,8 +85,8 @@ class Usher
|
|
109
85
|
elsif path.size.zero? && !part
|
110
86
|
if terminates?
|
111
87
|
Response.new(terminates, params)
|
112
|
-
|
113
|
-
nil
|
88
|
+
elsif params.last.is_a?(Array) && @lookup[nil]
|
89
|
+
Response.new(@lookup[nil].terminates, params)
|
114
90
|
end
|
115
91
|
elsif next_part = @lookup[part]
|
116
92
|
next_part.find(request, path, params)
|
@@ -120,16 +96,14 @@ class Usher
|
|
120
96
|
next_part.value.valid!(part)
|
121
97
|
case next_part.value.type
|
122
98
|
when :*
|
123
|
-
params << [next_part.value.name, []]
|
124
|
-
params.last.last << part
|
99
|
+
params << [next_part.value.name, []] unless params.last && params.last.first == next_part.value.name
|
100
|
+
params.last.last << part unless part.is_a?(Symbol)
|
101
|
+
find(request, path, params)
|
125
102
|
when :':'
|
126
103
|
params << [next_part.value.name, part]
|
104
|
+
next_part.find(request, path, params)
|
127
105
|
end
|
128
106
|
end
|
129
|
-
next_part.find(request, path, params)
|
130
|
-
elsif has_globber? && p = find_parent{|p| p.value.is_a?(Route::Variable) && p.value.type == :*}
|
131
|
-
params.last.last << part
|
132
|
-
find(request, path, params)
|
133
107
|
else
|
134
108
|
nil
|
135
109
|
end
|
data/spec/generate_spec.rb
CHANGED
@@ -80,9 +80,18 @@ describe "Usher URL generation" do
|
|
80
80
|
proc {route_set.generate_url(route_set.add_route('/:controller/:action').primary_path, {:controller => 'controller'})}.should raise_error Usher::MissingParameterException
|
81
81
|
end
|
82
82
|
|
83
|
+
it "should generate from a route" do
|
84
|
+
route_set.generate_url(route_set.add_route('/:controller/:action'), {:controller => 'controller', :action => 'action'}).should == '/controller/action'
|
85
|
+
end
|
86
|
+
|
83
87
|
it "should require all the parameters (array) to generate a route" do
|
84
88
|
route_set.add_named_route(:name, '/:controller/:action.:format')
|
85
89
|
proc {route_set.generate_url(:name, ['controller', 'action'])}.should raise_error Usher::MissingParameterException
|
86
90
|
end
|
87
91
|
|
92
|
+
it "should generate a route when only one parameter is given" do
|
93
|
+
route_set.add_named_route(:name, '/:controller')
|
94
|
+
route_set.generate_url(:name, 'controller').should == '/controller'
|
95
|
+
end
|
96
|
+
|
88
97
|
end
|
data/spec/grapher_spec.rb
CHANGED
@@ -19,6 +19,11 @@ describe "Usher grapher" do
|
|
19
19
|
route_set.generate_url(nil, {:a => 'A', :b => 'B', :c => 'C'}).should == '/A/B/C'
|
20
20
|
end
|
21
21
|
|
22
|
+
it "should fail to generate a route when none matches" do
|
23
|
+
route_set.add_route('/:a/:b')
|
24
|
+
proc {route_set.generate_url(nil, {:c => 'C', :d => 'D'}) }.should raise_error Usher::UnrecognizedException
|
25
|
+
end
|
26
|
+
|
22
27
|
it "should find the most specific route and append extra parts on as a query string" do
|
23
28
|
route_set.add_route('/:a/:b/:c')
|
24
29
|
route_set.add_route('/:a/:b')
|
data/spec/path_spec.rb
CHANGED
@@ -36,4 +36,33 @@ describe "Usher route adding" do
|
|
36
36
|
route_set.add_named_route(:route, '/bad/route', :controller => 'sample').should == route_set.named_routes[:route]
|
37
37
|
end
|
38
38
|
|
39
|
+
it "should calculate depths for nodes" do
|
40
|
+
route_set.add_named_route(:route, '/bad/route/three/four')
|
41
|
+
route_set.tree.depth.should == 0
|
42
|
+
route_set.tree.lookup[:/].depth.should == 1
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should pp for nodes" do
|
46
|
+
route_set.add_named_route(:route, '/bad/route/three/four')
|
47
|
+
route_set.tree.depth.should == 0
|
48
|
+
old_out = $stdout
|
49
|
+
$stdout = (output = StringIO.new)
|
50
|
+
route_set.tree.lookup[:/].lookup['bad'].lookup[:/].pp
|
51
|
+
$stdout = old_out
|
52
|
+
output.rewind
|
53
|
+
output.read.should == <<-HEREDOC
|
54
|
+
3: :/ false
|
55
|
+
route ==>
|
56
|
+
4: "route" false
|
57
|
+
/ ==>
|
58
|
+
5: :/ false
|
59
|
+
three ==>
|
60
|
+
6: "three" false
|
61
|
+
/ ==>
|
62
|
+
7: :/ false
|
63
|
+
four ==>
|
64
|
+
8: "four" true
|
65
|
+
HEREDOC
|
66
|
+
end
|
67
|
+
|
39
68
|
end
|
data/spec/recognize_spec.rb
CHANGED
@@ -35,6 +35,11 @@ describe "Usher route recognition" do
|
|
35
35
|
route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [[:format , 'html']])
|
36
36
|
end
|
37
37
|
|
38
|
+
it "should recognize a glob-style variable" do
|
39
|
+
target_route = route_set.add_route('/sample/*format', :controller => 'sample', :action => 'action')
|
40
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample/html/json/apple'})).params.should == [[:format, ['html', 'json', 'apple']]]
|
41
|
+
end
|
42
|
+
|
38
43
|
it "should recognize a format-style literal" do
|
39
44
|
target_route = route_set.add_route('/:action.html', :controller => 'sample', :action => 'action')
|
40
45
|
route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [[:action , 'sample']])
|
@@ -72,11 +77,26 @@ describe "Usher route recognition" do
|
|
72
77
|
insecure_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :domain => 'admin.host.com', :user_agent => false})).path.route
|
73
78
|
end
|
74
79
|
|
80
|
+
it "should use conditionals that are arrays" do
|
81
|
+
# hijacking user_agent
|
82
|
+
www_product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['www'], :method => 'get'})
|
83
|
+
admin_product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['admin'], :method => 'get'})
|
84
|
+
|
85
|
+
admin_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => ['admin'], :user_agent => true})).path.route
|
86
|
+
www_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => ['www'], :user_agent => false})).path.route
|
87
|
+
end
|
88
|
+
|
75
89
|
it "should use a transformer (proc) on incoming variables" do
|
76
90
|
route_set.add_route('/:controller/:action/:id', :transformers => {:id => proc{|v| v.to_i}})
|
77
91
|
route_set.recognize(build_request({:method => 'get', :path => '/products/show/123asd', :domain => 'admin.host.com'})).params.rassoc(123).first.should == :id
|
78
92
|
end
|
79
93
|
|
94
|
+
it "should use a requirement (proc) on incoming variables" do
|
95
|
+
route_set.add_route('/:controller/:action/:id', :id => proc{|v| Integer(v)})
|
96
|
+
proc {route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :domain => 'admin.host.com'}))}.should_not raise_error Usher::ValidationException
|
97
|
+
proc {route_set.recognize(build_request({:method => 'get', :path => '/products/show/123asd', :domain => 'admin.host.com'}))}.should raise_error Usher::ValidationException
|
98
|
+
end
|
99
|
+
|
80
100
|
it "shouldn't care about mildly weird characters in the URL" do
|
81
101
|
route = route_set.add_route('/!asd,qwe/hjk$qwe/:id')
|
82
102
|
route_set.recognize(build_request({:method => 'get', :path => '/!asd,qwe/hjk$qwe/09AZaz$-_+!*\'', :domain => 'admin.host.com'})).params.rassoc('09AZaz$-_+!*\'').first.should == :id
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'lib/usher'
|
2
|
+
|
3
|
+
describe "Usher request method" do
|
4
|
+
|
5
|
+
it "support eql? and ==" do
|
6
|
+
Usher::Route::RequestMethod.new(:method, 'blah').should == Usher::Route::RequestMethod.new(:method, 'blah')
|
7
|
+
Usher::Route::RequestMethod.new(:method, 'blah').should.eql?(Usher::Route::RequestMethod.new(:method, 'blah'))
|
8
|
+
end
|
9
|
+
|
10
|
+
it "support hash" do
|
11
|
+
Usher::Route::RequestMethod.new(:method, 'blah').hash.should == (Usher::Route::RequestMethod.new(:method, 'blah')).hash
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
end
|
data/spec/split_spec.rb
CHANGED
@@ -53,5 +53,15 @@ describe "Usher route tokenizing" do
|
|
53
53
|
[:/, "test", :/, "this", :/, "split", '.', Usher::Route::Variable.new(:':', :format)]
|
54
54
|
]
|
55
55
|
end
|
56
|
+
|
57
|
+
it "should to_s all different variable types" do
|
58
|
+
Usher::Splitter.for_delimiters(['/', '.']).split('/:split/*splitter').first.collect{|v| v.to_s} ==
|
59
|
+
[ ':split', '*splitter' ]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should == variable types" do
|
63
|
+
parts = Usher::Splitter.for_delimiters(['/', '.']).split('/:split/:split').first
|
64
|
+
parts[1].should == parts[3]
|
65
|
+
end
|
56
66
|
|
57
67
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: joshbuddy-usher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Hull
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-07 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- spec/rails/path_spec.rb
|
69
69
|
- spec/rails/recognize_spec.rb
|
70
70
|
- spec/recognize_spec.rb
|
71
|
+
- spec/request_method_spec.rb
|
71
72
|
- spec/spec.opts
|
72
73
|
- spec/split_spec.rb
|
73
74
|
- rails/init.rb
|