usher 0.6.3 → 0.6.4
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 +1 -3
- data/VERSION.yml +1 -1
- data/lib/usher/interface/email.rb +4 -4
- data/lib/usher/interface/rack.rb +17 -13
- data/lib/usher/interface/rails22.rb +1 -1
- data/lib/usher/interface/rails23.rb +59 -60
- data/lib/usher/node/response.rb +22 -0
- data/lib/usher/node/root.rb +140 -0
- data/lib/usher/node.rb +48 -196
- data/lib/usher/route/path.rb +17 -17
- data/lib/usher/route.rb +18 -18
- data/lib/usher/util/mapper.rb +9 -0
- data/lib/usher/util.rb +1 -0
- data/lib/usher.rb +5 -1
- data/spec/private/rack/dispatch_spec.rb +15 -0
- data/spec/private/rails2_3/recognize_spec.rb +9 -9
- data/spec/private/recognize_spec.rb +13 -9
- metadata +7 -4
data/Rakefile
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'usher'))
|
4
|
-
|
5
3
|
begin
|
6
4
|
require 'jeweler'
|
7
5
|
Jeweler::Tasks.new do |s|
|
8
6
|
s.name = "usher"
|
9
|
-
s.description = s.summary = "
|
7
|
+
s.description = s.summary = "Pure ruby general purpose router with interfaces for rails, rack, email or choose your own adventure"
|
10
8
|
s.email = "joshbuddy@gmail.com"
|
11
9
|
s.homepage = "http://github.com/joshbuddy/usher"
|
12
10
|
s.authors = ["Joshua Hull", 'Jakub Šťastný', 'Daniel Neighman', 'Daniel Vartanov'].sort
|
data/VERSION.yml
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
class Usher
|
2
2
|
module Interface
|
3
3
|
class Email
|
4
|
-
|
4
|
+
|
5
5
|
def initialize(&blk)
|
6
6
|
@routes = Usher.new(:delimiters => ['@', '-', '.'], :valid_regex => '[\+a-zA-Z0-9]+')
|
7
7
|
instance_eval(&blk) if blk
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def for(path, &block)
|
11
11
|
@routes.add_route(path).to(block)
|
12
12
|
end
|
@@ -18,10 +18,10 @@ class Usher
|
|
18
18
|
def act(email)
|
19
19
|
response = @routes.recognize(email, email)
|
20
20
|
if response.path
|
21
|
-
response.path.route.destination.call(response.
|
21
|
+
response.path.route.destination.call(response.params_as_hash)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
end
|
26
26
|
end
|
27
|
-
end
|
27
|
+
end
|
data/lib/usher/interface/rack.rb
CHANGED
@@ -4,24 +4,24 @@ require File.join(File.dirname(__FILE__), 'rack', 'route')
|
|
4
4
|
class Usher
|
5
5
|
module Interface
|
6
6
|
class Rack
|
7
|
-
|
7
|
+
|
8
8
|
ENV_KEY_RESPONSE = 'usher.response'
|
9
9
|
ENV_KEY_PARAMS = 'usher.params'
|
10
|
-
|
10
|
+
|
11
11
|
class Middleware
|
12
|
-
|
12
|
+
|
13
13
|
def initialize(app, router)
|
14
14
|
@app = app
|
15
15
|
@router = router
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def call(env)
|
19
19
|
@router.call(env)
|
20
20
|
@app.call(env)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
class Builder < ::Rack::Builder
|
26
26
|
def initialize(&block)
|
27
27
|
@usher = Usher::Interface::Rack.new
|
@@ -79,7 +79,7 @@ class Usher
|
|
79
79
|
@router.add_route(path, options)
|
80
80
|
end
|
81
81
|
alias_method :path, :add
|
82
|
-
|
82
|
+
|
83
83
|
# default { |env| ... }
|
84
84
|
# default DefaultApp
|
85
85
|
def default(app = nil, &block)
|
@@ -138,14 +138,14 @@ class Usher
|
|
138
138
|
# @api plugin
|
139
139
|
def after_match(request, response)
|
140
140
|
params = response.path.route.default_values ? response.path.route.default_values.merge(response.params_as_hash) : response.params_as_hash
|
141
|
-
|
141
|
+
|
142
142
|
request.env[ENV_KEY_RESPONSE] ||= []
|
143
143
|
request.env[ENV_KEY_RESPONSE] << response
|
144
144
|
|
145
145
|
request.env[ENV_KEY_PARAMS] ?
|
146
146
|
request.env[ENV_KEY_PARAMS].merge!(params) :
|
147
147
|
(request.env[ENV_KEY_PARAMS] = params)
|
148
|
-
|
148
|
+
|
149
149
|
# consume the path_info to the script_name
|
150
150
|
# response.remaining_path
|
151
151
|
consume_path!(request, response) if response.partial_match?
|
@@ -159,7 +159,11 @@ class Usher
|
|
159
159
|
#
|
160
160
|
# @api private
|
161
161
|
def determine_respondant(response)
|
162
|
-
use_destinations? && response && response.destination
|
162
|
+
if use_destinations? && response && response.destination && response.destination.respond_to?(:call)
|
163
|
+
response.destination
|
164
|
+
else
|
165
|
+
_app
|
166
|
+
end
|
163
167
|
end
|
164
168
|
|
165
169
|
# Consume the path from path_info to script_name
|
@@ -167,14 +171,14 @@ class Usher
|
|
167
171
|
request.env["SCRIPT_NAME"] = (request.env["SCRIPT_NAME"] + response.matched_path) || ""
|
168
172
|
request.env["PATH_INFO"] = response.remaining_path || ""
|
169
173
|
end
|
170
|
-
|
174
|
+
|
171
175
|
def default_app
|
172
176
|
_app
|
173
177
|
end
|
174
|
-
|
178
|
+
|
175
179
|
private
|
176
180
|
attr_reader :_app
|
177
|
-
|
181
|
+
|
178
182
|
end
|
179
183
|
end
|
180
184
|
end
|
@@ -46,7 +46,7 @@ class Usher
|
|
46
46
|
|
47
47
|
def recognize(request)
|
48
48
|
node = @usher.recognize(request)
|
49
|
-
params = node.
|
49
|
+
params = node.params_as_hash
|
50
50
|
request.path_parameters = (node.params.empty? ? node.path.route.destination : node.path.route.destination.merge(params)).with_indifferent_access
|
51
51
|
"#{request.path_parameters[:controller].camelize}Controller".constantize
|
52
52
|
rescue
|
@@ -1,13 +1,13 @@
|
|
1
1
|
class Usher
|
2
2
|
module Interface
|
3
3
|
class Rails23
|
4
|
-
|
4
|
+
|
5
5
|
attr_reader :configuration_files
|
6
|
-
|
6
|
+
|
7
7
|
def named_routes
|
8
8
|
@router.named_routes
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def add_named_route(name, route, options = {})
|
12
12
|
@router.add_route(route, options).name(name)
|
13
13
|
end
|
@@ -15,38 +15,38 @@ class Usher
|
|
15
15
|
def add_route(path, options = {})
|
16
16
|
if !@controller_action_route_added && path =~ %r{^/?:controller/:action/:id$}
|
17
17
|
add_route('/:controller/:action', options.dup)
|
18
|
-
@controller_action_route_added = true
|
18
|
+
@controller_action_route_added = true
|
19
19
|
end
|
20
20
|
|
21
21
|
if !@controller_route_added && path =~ %r{^/?:controller/:action$}
|
22
22
|
add_route('/:controller', options.merge({:action => 'index'}))
|
23
|
-
@controller_route_added = true
|
23
|
+
@controller_route_added = true
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
options[:action] = 'index' unless options[:action]
|
27
27
|
|
28
28
|
path[0, 0] = '/' unless path[0] == ?/
|
29
29
|
route = @router.add_route(path, options).to(options)
|
30
|
-
|
30
|
+
|
31
31
|
raise "your route must include a controller" unless (route.paths.first.dynamic_keys && route.paths.first.dynamic_keys.include?(:controller)) || route.destination.include?(:controller)
|
32
32
|
route
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def initialize
|
36
36
|
reset!
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def add_configuration_file(file)
|
40
40
|
@configuration_files << file
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def reload!
|
44
44
|
if configuration_files.any?
|
45
45
|
configuration_files.each { |config| load(config) }
|
46
46
|
else
|
47
47
|
add_route ":controller/:action/:id"
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
end
|
51
51
|
alias_method :reload, :reload!
|
52
52
|
|
@@ -63,75 +63,74 @@ class Usher
|
|
63
63
|
app = recognize(request)
|
64
64
|
app.call(env).to_a
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
def recognize(request)
|
68
68
|
response = @router.recognize(request)
|
69
|
-
request.path_parameters
|
70
|
-
response.params.each { |pair| request.path_parameters[pair.first] = pair.last }
|
69
|
+
request.path_parameters.merge!(response.params_as_hash)
|
71
70
|
"#{request.path_parameters[:controller].camelize}Controller".constantize
|
72
71
|
end
|
73
|
-
|
72
|
+
|
74
73
|
def reset!(options={})
|
75
74
|
options[:generator] = options[:generator] || Usher::Util::Generators::URL.new
|
76
75
|
options[:request_methods] = options[:request_methods] || [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains]
|
77
|
-
|
76
|
+
|
78
77
|
@router = Usher.new(options)
|
79
78
|
@configuration_files = []
|
80
79
|
@module ||= Module.new
|
81
80
|
@controller_route_added = false
|
82
81
|
@controller_action_route_added = false
|
83
82
|
end
|
84
|
-
|
83
|
+
|
85
84
|
def draw(options={})
|
86
85
|
reset!(options)
|
87
86
|
yield ActionController::Routing::RouteSet::Mapper.new(self)
|
88
87
|
install_helpers
|
89
88
|
end
|
90
|
-
|
89
|
+
|
91
90
|
def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false)
|
92
91
|
#*_url and hash_for_*_url
|
93
|
-
Array(destinations).each do |d| d.module_eval { include Helpers }
|
92
|
+
Array(destinations).each do |d| d.module_eval { include Helpers }
|
94
93
|
@router.named_routes.keys.each do |name|
|
95
94
|
@module.module_eval <<-end_eval # We use module_eval to avoid leaks
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
95
|
+
def #{name}_url(options = {})
|
96
|
+
ActionController::Routing::UsherRoutes.generate(options, {}, :generate, :#{name})
|
97
|
+
end
|
98
|
+
end_eval
|
99
|
+
end
|
100
|
+
d.__send__(:include, @module)
|
101
|
+
end
|
102
|
+
end
|
104
103
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
104
|
+
def generate(options, recall = {}, method = :generate, route_name = nil)
|
105
|
+
route = if(route_name)
|
106
|
+
@router.named_routes[route_name]
|
107
|
+
else
|
108
|
+
merged_options = options
|
109
|
+
merged_options[:controller] = recall[:controller] unless options.key?(:controller)
|
110
|
+
unless options.key?(:action)
|
111
|
+
options[:action] = ''
|
112
|
+
end
|
113
|
+
path_for_options(merged_options)
|
114
|
+
end
|
115
|
+
case method
|
116
|
+
when :generate
|
117
|
+
merged_options ||= recall.merge(options)
|
118
|
+
url = generate_url(route, merged_options)
|
119
|
+
url.slice!(-1) if url[-1] == ?/
|
120
|
+
url
|
121
|
+
else
|
122
|
+
raise "method #{method} not recognized"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def generate_url(route, params)
|
127
|
+
@router.generator.generate(route, params)
|
128
|
+
end
|
129
|
+
|
130
|
+
def path_for_options(options)
|
131
|
+
@router.path_for_options(options)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Usher
|
2
|
+
class Node
|
3
|
+
class Response < Struct.new(:path, :params_as_array, :remaining_path, :matched_path)
|
4
|
+
|
5
|
+
def params
|
6
|
+
@params ||= params_as_array.nil? ? [] : path.convert_params_array(params_as_array)
|
7
|
+
end
|
8
|
+
|
9
|
+
def partial_match?
|
10
|
+
!remaining_path.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
def params_as_hash
|
14
|
+
@params_as_hash ||= params_as_array.nil? ? {} : params_as_array.inject({}){|hash, val| hash[path.dynamic_keys[hash.size]] = val; hash}
|
15
|
+
end
|
16
|
+
|
17
|
+
def destination
|
18
|
+
path && path.route.destination
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
class Usher
|
2
|
+
class Node
|
3
|
+
class Root < Node
|
4
|
+
|
5
|
+
def initialize(route_set, request_methods)
|
6
|
+
super(route_set, nil)
|
7
|
+
self.request_methods = request_methods
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(route)
|
11
|
+
route.paths.each do |path|
|
12
|
+
set_path_with_destination(path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete(route)
|
17
|
+
route.paths.each do |path|
|
18
|
+
set_path_with_destination(path, nil)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def unique_routes(node = self, routes = [])
|
23
|
+
routes << node.terminates.route if node.terminates
|
24
|
+
node.normal.values.each do |v|
|
25
|
+
unique_routes(v, routes)
|
26
|
+
end if node.normal
|
27
|
+
node.greedy.values.each do |v|
|
28
|
+
unique_routes(v, routes)
|
29
|
+
end if node.greedy
|
30
|
+
node.request.values.each do |v|
|
31
|
+
unique_routes(v, routes)
|
32
|
+
end if node.request
|
33
|
+
routes.uniq!
|
34
|
+
routes
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def set_path_with_destination(path, destination = path)
|
40
|
+
nodes = [path.parts.inject(self){ |node, key| process_path_part(node, key) }]
|
41
|
+
nodes = process_request_parts(nodes, request_methods_for_path(path)) if request_methods
|
42
|
+
|
43
|
+
nodes.each do |node|
|
44
|
+
while node.request_method_type
|
45
|
+
node = (node.request[nil] ||= Node.new(node, Route::RequestMethod.new(node.request_method_type, nil)))
|
46
|
+
end
|
47
|
+
node.terminates = destination
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def request_method_index(type)
|
52
|
+
request_methods.index(type)
|
53
|
+
end
|
54
|
+
|
55
|
+
def process_request_parts(nodes, parts)
|
56
|
+
while parts.any?{ |p| !p.trivial? }
|
57
|
+
key = parts.shift
|
58
|
+
|
59
|
+
next if key.trivial?
|
60
|
+
nodes.map! do |node|
|
61
|
+
node.activate_request!
|
62
|
+
if node.request_method_type.nil?
|
63
|
+
node.request_method_type = key.type
|
64
|
+
node.upgrade_request! if key.value.is_a?(Regexp)
|
65
|
+
Array(key.value).map{|k| node.request[k] ||= Node.new(node, key) }
|
66
|
+
else
|
67
|
+
case request_method_index(node.request_method_type) <=> request_method_index(key.type)
|
68
|
+
when -1
|
69
|
+
parts.unshift(key)
|
70
|
+
Array(key.value).map{|k| node.request[nil] ||= Node.new(node, Route::RequestMethod.new(node.request_method_type, nil)) }
|
71
|
+
when 0
|
72
|
+
node.upgrade_request! if key.value.is_a?(Regexp)
|
73
|
+
Array(key.value).map{|k| node.request[k] ||= Node.new(node, key) }
|
74
|
+
when 1
|
75
|
+
previous_node = node.parent
|
76
|
+
current_node_entry_key = nil
|
77
|
+
current_node_entry_lookup = nil
|
78
|
+
[previous_node.normal, previous_node.greedy, previous_node.request].compact.each do |l|
|
79
|
+
current_node_entry_key = l.each{|k,v| break k if node == v}
|
80
|
+
current_node_entry_lookup = l and break if current_node_entry_key
|
81
|
+
end
|
82
|
+
|
83
|
+
current_node_entry_lookup.respond_to?(:delete_value) ?
|
84
|
+
current_node_entry_lookup.delete_value(node) : current_node_entry_lookup.delete_if{|k,v| v == node}
|
85
|
+
|
86
|
+
new_node = Node.new(previous_node, Route::RequestMethod.new(key.type, nil))
|
87
|
+
new_node.activate_request!
|
88
|
+
new_node.request_method_type = key.type
|
89
|
+
current_node_entry_lookup[current_node_entry_key] = new_node
|
90
|
+
node.parent = new_node
|
91
|
+
new_node.request[nil] = node
|
92
|
+
parts.unshift(key)
|
93
|
+
new_node
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
nodes.flatten!
|
98
|
+
end
|
99
|
+
nodes
|
100
|
+
end
|
101
|
+
|
102
|
+
def process_path_part(node, key)
|
103
|
+
case key
|
104
|
+
when Route::Variable::Greedy
|
105
|
+
node.activate_greedy!
|
106
|
+
if key.regex_matcher
|
107
|
+
node.upgrade_greedy!
|
108
|
+
node.greedy[key.regex_matcher] ||= Node.new(node, key)
|
109
|
+
else
|
110
|
+
node.greedy[nil] ||= Node.new(node, key)
|
111
|
+
end
|
112
|
+
when Route::Variable
|
113
|
+
node.activate_normal!
|
114
|
+
if key.regex_matcher
|
115
|
+
node.upgrade_normal!
|
116
|
+
node.normal[key.regex_matcher] ||= Node.new(node, key)
|
117
|
+
else
|
118
|
+
node.normal[nil] ||= Node.new(node, key)
|
119
|
+
end
|
120
|
+
when Route::Static::Greedy
|
121
|
+
node.activate_greedy!
|
122
|
+
node.upgrade_greedy!
|
123
|
+
node.greedy[key] ||= Node.new(node, key)
|
124
|
+
else
|
125
|
+
node.activate_normal!
|
126
|
+
node.upgrade_normal! if key.is_a?(Regexp)
|
127
|
+
node.normal[key] ||= Node.new(node, key)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def request_methods_for_path(path)
|
132
|
+
request_methods.collect do |type|
|
133
|
+
Route::RequestMethod.new(type, path.route.conditions && path.route.conditions[type])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
data/lib/usher/node.rb
CHANGED
@@ -1,23 +1,9 @@
|
|
1
|
-
require '
|
1
|
+
require File.join('usher', 'node', 'root')
|
2
|
+
require File.join('usher', 'node', 'response')
|
2
3
|
|
3
4
|
class Usher
|
4
|
-
|
5
5
|
class Node
|
6
|
-
|
7
|
-
class Response < Struct.new(:path, :params, :remaining_path, :matched_path)
|
8
|
-
def partial_match?
|
9
|
-
!remaining_path.nil?
|
10
|
-
end
|
11
|
-
|
12
|
-
def params_as_hash
|
13
|
-
params.inject({}){|hash, pair| hash[pair.first] = pair.last; hash}
|
14
|
-
end
|
15
|
-
|
16
|
-
def destination
|
17
|
-
path && path.route.destination
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
6
|
+
|
21
7
|
attr_reader :normal, :greedy, :request
|
22
8
|
attr_accessor :terminates, :request_method_type, :parent, :value, :request_methods
|
23
9
|
|
@@ -29,7 +15,7 @@ class Usher
|
|
29
15
|
@greedy = nil
|
30
16
|
@request_method_type = nil
|
31
17
|
end
|
32
|
-
|
18
|
+
|
33
19
|
def activate_normal!
|
34
20
|
@normal ||= Hash.new
|
35
21
|
end
|
@@ -57,16 +43,10 @@ class Usher
|
|
57
43
|
def depth
|
58
44
|
@depth ||= @parent.is_a?(Node) ? @parent.depth + 1 : 0
|
59
45
|
end
|
60
|
-
|
46
|
+
|
61
47
|
def greedy?
|
62
48
|
@greedy
|
63
49
|
end
|
64
|
-
|
65
|
-
def self.root(route_set, request_methods)
|
66
|
-
root = self.new(route_set, nil)
|
67
|
-
root.request_methods = request_methods
|
68
|
-
root
|
69
|
-
end
|
70
50
|
|
71
51
|
def terminates?
|
72
52
|
@terminates && @terminates.route.recognizable?
|
@@ -91,95 +71,68 @@ class Usher
|
|
91
71
|
v.pp
|
92
72
|
end if request
|
93
73
|
end
|
94
|
-
|
95
|
-
def
|
96
|
-
route.paths.each do |path|
|
97
|
-
set_path_with_destination(path)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def delete(route)
|
102
|
-
route.paths.each do |path|
|
103
|
-
set_path_with_destination(path, nil)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def unique_routes(node = self, routes = [])
|
108
|
-
routes << node.terminates.route if node.terminates
|
109
|
-
node.normal.values.each do |v|
|
110
|
-
unique_routes(v, routes)
|
111
|
-
end if node.normal
|
112
|
-
node.greedy.values.each do |v|
|
113
|
-
unique_routes(v, routes)
|
114
|
-
end if node.greedy
|
115
|
-
node.request.values.each do |v|
|
116
|
-
unique_routes(v, routes)
|
117
|
-
end if node.request
|
118
|
-
routes.uniq!
|
119
|
-
routes
|
120
|
-
end
|
121
|
-
|
122
|
-
def find(usher, request_object, original_path, path, params = [], position = 0)
|
74
|
+
|
75
|
+
def find(usher, request_object, original_path, path, params = nil, position = 0)
|
123
76
|
if terminates? && (path.empty? || terminates.route.partial_match? || (usher.ignore_trailing_delimiters? && path.all?{|p| usher.delimiters.include?(p)}))
|
124
77
|
terminates.route.partial_match? ?
|
125
|
-
Response.new(terminates,
|
126
|
-
Response.new(terminates,
|
78
|
+
Response.new(terminates, params, original_path[position, original_path.size], original_path[0, position]) :
|
79
|
+
Response.new(terminates, params, nil, original_path)
|
127
80
|
elsif !path.empty? and greedy and match_with_result_output = greedy.match_with_result(whole_path = original_path[position, original_path.size])
|
128
|
-
|
81
|
+
next_path, matched_part = match_with_result_output
|
129
82
|
position += matched_part.size
|
130
83
|
whole_path.slice!(0, matched_part.size)
|
131
|
-
params << matched_part if next_path.value.is_a?(Route::Variable)
|
84
|
+
(params ||= []) << matched_part if next_path.value.is_a?(Route::Variable)
|
132
85
|
next_path.find(usher, request_object, original_path, whole_path.empty? ? whole_path : usher.splitter.split(whole_path), params, position)
|
133
86
|
elsif !path.empty? and normal and next_part = normal[path.first] || normal[nil]
|
134
87
|
part = path.shift
|
135
88
|
position += part.size
|
136
89
|
case next_part.value
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
90
|
+
when String
|
91
|
+
# do nothing
|
92
|
+
when Route::Variable::Single
|
93
|
+
# get the variable
|
94
|
+
var = next_part.value
|
95
|
+
# do a validity check
|
96
|
+
var.valid!(part)
|
97
|
+
# because its a variable, we need to add it to the params array
|
98
|
+
(params ||= []) << part
|
99
|
+
until path.empty? || (var.look_ahead === path.first) # variables have a look ahead notion,
|
100
|
+
next_path_part = path.shift # and until they are satified,
|
101
|
+
position += next_path_part.size # keep appending to the value in params
|
102
|
+
params.last << next_path_part
|
103
|
+
end if var.look_ahead && usher.delimiters.size > 1
|
104
|
+
when Route::Variable::Glob
|
105
|
+
(params ||= []) << []
|
106
|
+
while true
|
107
|
+
if (next_part.value.look_ahead === part || (!usher.delimiters.unescaped.include?(part) && next_part.value.regex_matcher && !next_part.value.regex_matcher.match(part)))
|
108
|
+
path.unshift(part)
|
109
|
+
position -= part.size
|
110
|
+
if usher.delimiters.unescaped.include?(next_part.parent.value)
|
111
|
+
path.unshift(next_part.parent.value)
|
112
|
+
position -= next_part.parent.value.size
|
113
|
+
end
|
114
|
+
break
|
115
|
+
elsif !usher.delimiters.unescaped.include?(part)
|
116
|
+
next_part.value.valid!(part)
|
117
|
+
params.last << part
|
118
|
+
end
|
119
|
+
if path.empty?
|
120
|
+
break
|
121
|
+
else
|
122
|
+
part = path.shift
|
160
123
|
end
|
161
|
-
break
|
162
|
-
elsif !usher.delimiters.unescaped.include?(part)
|
163
|
-
next_part.value.valid!(part)
|
164
|
-
params.last << part
|
165
|
-
end
|
166
|
-
if path.empty?
|
167
|
-
break
|
168
|
-
else
|
169
|
-
part = path.shift
|
170
124
|
end
|
171
|
-
end
|
172
125
|
end
|
173
126
|
next_part.find(usher, request_object, original_path, path, params, position)
|
174
127
|
elsif request_method_type
|
175
|
-
return_value = if (specific_node = request[request_object.send(request_method_type)] and ret = specific_node.find(usher, request_object, original_path, path.dup, params.dup, position))
|
128
|
+
return_value = if (specific_node = request[request_object.send(request_method_type)] and ret = specific_node.find(usher, request_object, original_path, path.dup, params && params.dup, position))
|
176
129
|
usher.priority_lookups? ? [ret] : ret
|
177
130
|
end
|
178
|
-
|
179
|
-
if usher.priority_lookups? || return_value.nil? and general_node = request[nil] and ret = general_node.find(usher, request_object, original_path, path.dup, params.dup, position)
|
131
|
+
|
132
|
+
if usher.priority_lookups? || return_value.nil? and general_node = request[nil] and ret = general_node.find(usher, request_object, original_path, path.dup, params && params.dup, position)
|
180
133
|
return_value = usher.priority_lookups? && return_value ? [return_value, ret] : ret
|
181
134
|
end
|
182
|
-
|
135
|
+
|
183
136
|
unless usher.priority_lookups?
|
184
137
|
return_value
|
185
138
|
else
|
@@ -192,106 +145,5 @@ class Usher
|
|
192
145
|
end
|
193
146
|
end
|
194
147
|
|
195
|
-
private
|
196
|
-
|
197
|
-
def set_path_with_destination(path, destination = path)
|
198
|
-
nodes = [path.parts.inject(self){ |node, key| process_path_part(node, key) }]
|
199
|
-
nodes = process_request_parts(nodes, request_methods_for_path(path)) if request_methods
|
200
|
-
|
201
|
-
nodes.each do |node|
|
202
|
-
while node.request_method_type
|
203
|
-
node = (node.request[nil] ||= Node.new(node, Route::RequestMethod.new(node.request_method_type, nil)))
|
204
|
-
end
|
205
|
-
node.terminates = destination
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def request_method_index(type)
|
210
|
-
request_methods.index(type)
|
211
|
-
end
|
212
|
-
|
213
|
-
def process_request_parts(nodes, parts)
|
214
|
-
while parts.any?{ |p| !p.trivial? }
|
215
|
-
key = parts.shift
|
216
|
-
|
217
|
-
next if key.trivial?
|
218
|
-
nodes.map! do |node|
|
219
|
-
node.activate_request!
|
220
|
-
if node.request_method_type.nil?
|
221
|
-
node.request_method_type = key.type
|
222
|
-
node.upgrade_request! if key.value.is_a?(Regexp)
|
223
|
-
Array(key.value).map{|k| node.request[k] ||= Node.new(node, key) }
|
224
|
-
else
|
225
|
-
case request_method_index(node.request_method_type) <=> request_method_index(key.type)
|
226
|
-
when -1
|
227
|
-
parts.unshift(key)
|
228
|
-
Array(key.value).map{|k| node.request[nil] ||= Node.new(node, Route::RequestMethod.new(node.request_method_type, nil)) }
|
229
|
-
when 0
|
230
|
-
node.upgrade_request! if key.value.is_a?(Regexp)
|
231
|
-
Array(key.value).map{|k| node.request[k] ||= Node.new(node, key) }
|
232
|
-
when 1
|
233
|
-
previous_node = node.parent
|
234
|
-
current_node_entry_key = nil
|
235
|
-
current_node_entry_lookup = nil
|
236
|
-
[previous_node.normal, previous_node.greedy, previous_node.request].compact.each do |l|
|
237
|
-
current_node_entry_key = l.each{|k,v| break k if node == v}
|
238
|
-
current_node_entry_lookup = l and break if current_node_entry_key
|
239
|
-
end
|
240
|
-
|
241
|
-
current_node_entry_lookup.respond_to?(:delete_value) ?
|
242
|
-
current_node_entry_lookup.delete_value(node) : current_node_entry_lookup.delete_if{|k,v| v == node}
|
243
|
-
|
244
|
-
new_node = Node.new(previous_node, Route::RequestMethod.new(key.type, nil))
|
245
|
-
new_node.activate_request!
|
246
|
-
new_node.request_method_type = key.type
|
247
|
-
current_node_entry_lookup[current_node_entry_key] = new_node
|
248
|
-
node.parent = new_node
|
249
|
-
new_node.request[nil] = node
|
250
|
-
parts.unshift(key)
|
251
|
-
new_node
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
255
|
-
nodes.flatten!
|
256
|
-
end
|
257
|
-
nodes
|
258
|
-
end
|
259
|
-
|
260
|
-
|
261
|
-
def process_path_part(node, key)
|
262
|
-
case key
|
263
|
-
when Route::Variable::Greedy
|
264
|
-
node.activate_greedy!
|
265
|
-
if key.regex_matcher
|
266
|
-
node.upgrade_greedy!
|
267
|
-
node.greedy[key.regex_matcher] ||= Node.new(node, key)
|
268
|
-
else
|
269
|
-
node.greedy[nil] ||= Node.new(node, key)
|
270
|
-
end
|
271
|
-
when Route::Variable
|
272
|
-
node.activate_normal!
|
273
|
-
if key.regex_matcher
|
274
|
-
node.upgrade_normal!
|
275
|
-
node.normal[key.regex_matcher] ||= Node.new(node, key)
|
276
|
-
else
|
277
|
-
node.normal[nil] ||= Node.new(node, key)
|
278
|
-
end
|
279
|
-
when Route::Static::Greedy
|
280
|
-
node.activate_greedy!
|
281
|
-
node.upgrade_greedy!
|
282
|
-
node.greedy[key] ||= Node.new(node, key)
|
283
|
-
else
|
284
|
-
node.activate_normal!
|
285
|
-
node.upgrade_normal! if key.is_a?(Regexp)
|
286
|
-
node.normal[key] ||= Node.new(node, key)
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
def request_methods_for_path(path)
|
291
|
-
request_methods.collect do |type|
|
292
|
-
Route::RequestMethod.new(type, path.route.conditions && path.route.conditions[type])
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
148
|
end
|
297
149
|
end
|
data/lib/usher/route/path.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
class Usher
|
2
2
|
class Route
|
3
3
|
class Path
|
4
|
-
|
4
|
+
|
5
5
|
attr_accessor :route
|
6
6
|
attr_reader :parts
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(route, parts)
|
9
9
|
self.route = route
|
10
10
|
self.parts = parts
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def convert_params_array(ary)
|
14
14
|
ary.empty? ? ary : dynamic_keys.zip(ary)
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def dynamic_indicies
|
18
18
|
unless dynamic? && @dynamic_indicies
|
19
19
|
@dynamic_indicies = []
|
@@ -33,15 +33,15 @@ class Usher
|
|
33
33
|
end
|
34
34
|
@dynamic_map
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def dynamic_keys
|
38
38
|
@dynamic_keys ||= dynamic_parts.map{|dp| dp.name} if dynamic?
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def dynamic_required_keys
|
42
42
|
@dynamic_required_keys ||= dynamic_parts.select{|dp| !dp.default_value}.map{|dp| dp.name} if dynamic?
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def dynamic?
|
46
46
|
@dynamic
|
47
47
|
end
|
@@ -51,26 +51,26 @@ class Usher
|
|
51
51
|
(dynamic_required_keys - keys).size.zero? ? keys : nil
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
def can_generate_from_params?(params)
|
56
56
|
if route.router.consider_destination_keys?
|
57
57
|
route.destination.to_a - params.to_a
|
58
58
|
(route.destination.to_a - params.to_a).size.zero?
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
# Merges paths for use in generation
|
63
63
|
def merge(other_path)
|
64
64
|
new_parts = parts + other_path.parts
|
65
65
|
Path.new(route, new_parts)
|
66
66
|
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
67
|
+
|
68
|
+
private
|
69
|
+
def parts=(parts)
|
70
|
+
@parts = parts
|
71
|
+
@dynamic = @parts.any?{|p| p.is_a?(Variable)}
|
72
|
+
end
|
73
|
+
|
74
74
|
end
|
75
75
|
end
|
76
|
-
end
|
76
|
+
end
|
data/lib/usher/route.rb
CHANGED
@@ -24,12 +24,12 @@ class Usher
|
|
24
24
|
|
25
25
|
def destination_keys
|
26
26
|
@destination_keys ||= case
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
when Hash
|
28
|
+
destination.keys
|
29
|
+
when CompoundDestination
|
30
|
+
destination.options.keys
|
31
|
+
else
|
32
|
+
nil
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -48,7 +48,7 @@ class Usher
|
|
48
48
|
end
|
49
49
|
@grapher
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
def unrecognizable!
|
53
53
|
self.recognizable = false
|
54
54
|
self
|
@@ -62,7 +62,7 @@ class Usher
|
|
62
62
|
def recognizable?
|
63
63
|
self.recognizable
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def dup
|
67
67
|
result = super
|
68
68
|
result.instance_eval do
|
@@ -78,11 +78,11 @@ class Usher
|
|
78
78
|
else
|
79
79
|
@paths.size == 1 ? @paths.first : grapher.find_matching_path(params)
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
if matching_path.nil? and router.find_matching_paths_based_on_destination_keys?
|
83
83
|
# do something
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
if parent_route
|
87
87
|
matching_path = parent_route.find_matching_path(params).merge(matching_path)
|
88
88
|
matching_path.route = self
|
@@ -105,19 +105,19 @@ class Usher
|
|
105
105
|
# route.to(:controller => 'testing', :action => 'index')
|
106
106
|
# set.recognize(Request.new('/test')).first.params => {:controller => 'testing', :action => 'index'}
|
107
107
|
#
|
108
|
-
#
|
108
|
+
#
|
109
109
|
#
|
110
110
|
def to(*args, &block)
|
111
111
|
if !args.empty? && block
|
112
112
|
@destination = CompoundDestination.new(args, block, args.last.is_a?(Hash) ? args.pop : {})
|
113
113
|
elsif block.nil?
|
114
114
|
case args.size
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
115
|
+
when 0
|
116
|
+
raise "destination should be set as something"
|
117
|
+
when 1
|
118
|
+
@destination = args.first
|
119
|
+
else
|
120
|
+
@destination = CompoundDestination.new(args, nil, args.last.is_a?(Hash) ? args.pop : {})
|
121
121
|
end
|
122
122
|
else
|
123
123
|
@destination = block
|
@@ -147,7 +147,7 @@ class Usher
|
|
147
147
|
end
|
148
148
|
|
149
149
|
private
|
150
|
-
|
150
|
+
attr_writer :grapher
|
151
151
|
|
152
152
|
end
|
153
153
|
end
|
data/lib/usher/util.rb
CHANGED
data/lib/usher.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'fuzzy_hash'
|
2
|
+
|
1
3
|
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
2
4
|
require File.join('usher', 'node')
|
3
5
|
require File.join('usher', 'route')
|
@@ -39,7 +41,7 @@ class Usher
|
|
39
41
|
# set.reset!
|
40
42
|
# set.empty? => true
|
41
43
|
def reset!
|
42
|
-
@root = Node.
|
44
|
+
@root = Node::Root.new(self, request_methods)
|
43
45
|
@named_routes = {}
|
44
46
|
@routes = []
|
45
47
|
@grapher = Grapher.new(self)
|
@@ -64,6 +66,8 @@ class Usher
|
|
64
66
|
# <tt>:consider_destination_keys</tt>: +true+ or +false+. (default: +false+) When generating, and using hash destinations, you can have
|
65
67
|
# Usher use the destination hash to match incoming params.
|
66
68
|
#
|
69
|
+
# <tt>:allow_identical_variable_names</tt>: +true+ or +false+. (default: +true+) When adding routes, allow identical variable names to be used.
|
70
|
+
#
|
67
71
|
# Example, you create a route with a destination of :controller => 'test', :action => 'action'. If you made a call to generator with :controller => 'test',
|
68
72
|
# :action => 'action', it would pick that route to use for generation.
|
69
73
|
def initialize(options = nil)
|
@@ -75,6 +75,21 @@ describe "Usher (for rack) route dispatching" do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
describe "non rack app destinations" do
|
79
|
+
it "should route to a default application when using a hash" do
|
80
|
+
$captures = []
|
81
|
+
@default_app = lambda do |e|
|
82
|
+
$captures << :default
|
83
|
+
Rack::Response.new("Default").finish
|
84
|
+
end
|
85
|
+
@router = Usher::Interface.for(:rack)
|
86
|
+
@router.default(@default_app)
|
87
|
+
@router.add("/default").to(:action => "default")
|
88
|
+
response = @router.call(Rack::MockRequest.env_for("/default"))
|
89
|
+
$captures.should == [:default]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
78
93
|
describe "mounted rack instances" do
|
79
94
|
before do
|
80
95
|
@bad_app = mock("bad_app")
|
@@ -10,7 +10,7 @@ def build_request_mock(path, method, params)
|
|
10
10
|
request.should_receive(:path).any_number_of_times.and_return(path)
|
11
11
|
request.should_receive(:method).any_number_of_times.and_return(method)
|
12
12
|
params = params.with_indifferent_access
|
13
|
-
request.should_receive(:path_parameters=).any_number_of_times.with(params)
|
13
|
+
request.should_receive(:path_parameters=).any_number_of_times.with(hash_including(params))
|
14
14
|
request.should_receive(:path_parameters).any_number_of_times.and_return(params)
|
15
15
|
request
|
16
16
|
end
|
@@ -45,36 +45,36 @@ describe "Usher (for rails 2.3) route recognition" do
|
|
45
45
|
route_set.add_route('/sample/test', :controller => 'sample', :action => 'action')
|
46
46
|
route_set.recognize(build_request_mock('/sample/test', 'get', {:controller => 'sample', :action => 'action'})).should == SampleController
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
it "should raise based upon an invalid param" do
|
50
50
|
route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample', :requirements => {:action => /\d+/})
|
51
51
|
proc { route_set.recognize(build_request_mock('/sample/asdqwe', :post, {})) }.should raise_error
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
it "should raise based upon an invalid route" do
|
55
55
|
route_set.add_named_route(:sample, '/sample', :controller => 'sample', :action => 'test')
|
56
56
|
proc { route_set.recognize(build_request_mock('/test/asdqwe', :post, {})) }.should raise_error
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
it "should add /:controller and /:controller/:action if /:controller/:action/:id is added" do
|
60
60
|
route_set.add_route('/:controller/:action/:id')
|
61
61
|
route_set.route_count.should == 3
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
it "should correctly recognize a format (dynamic path path with . delimiter)" do
|
65
65
|
route_set.add_route('/:controller/:action/:id.:format')
|
66
66
|
route_set.recognize(build_request_mock('/sample/test/123.html', 'get', {:controller => 'sample', :action => 'test', :id => '123', :format => 'html'})).should == SampleController
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
it "should support root nodes" do
|
70
70
|
route_set.add_route('/', :controller => 'sample')
|
71
71
|
route_set.recognize(build_request_mock('/', :get, {:controller => 'sample', :action => 'index'})).should == SampleController
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
it "should default action to 'index' when controller (and not index) is specified" do
|
75
75
|
route_set.add_route('/:controller/:action')
|
76
76
|
route_set.recognize(build_request_mock('/sample', :get, {:controller => 'sample', :action => 'index'})).should == SampleController
|
77
77
|
end
|
78
|
-
|
79
|
-
|
78
|
+
|
79
|
+
|
80
80
|
end
|
@@ -47,18 +47,18 @@ describe "Usher route recognition" do
|
|
47
47
|
@route_set.recognize(build_request({:method => 'put', :path => '/sample', :protocol => 'wacky', :domain => 'admin.spec.com', :user_agent => nil})).path.route.should == target_route_http_admin_generic
|
48
48
|
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
it "should recognize an empty path" do
|
52
52
|
@route_set.add_route('').to(:test)
|
53
53
|
@route_set.recognize(build_request({:path => ''})).path.route.destination.should == :test
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
it "should recognize an optionally empty path" do
|
57
57
|
@route_set.add_route('(/)').to(:test)
|
58
58
|
@route_set.recognize(build_request({:path => ''})).path.route.destination.should == :test
|
59
59
|
@route_set.recognize(build_request({:path => '/'})).path.route.destination.should == :test
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
it "should allow adding a pure regex" do
|
63
63
|
@route_set.add_route(/\/test\/(testing|gold)/).to(:test)
|
64
64
|
@route_set.recognize(build_request({:path => '/test/testing'})).path.route.destination.should == :test
|
@@ -92,7 +92,7 @@ describe "Usher route recognition" do
|
|
92
92
|
|
93
93
|
it "should recognize path with a trailing slash" do
|
94
94
|
@route_set = Usher.new(:request_methods => [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains], :ignore_trailing_delimiters => true)
|
95
|
-
|
95
|
+
|
96
96
|
target_route = @route_set.add_route('/path', :controller => 'sample', :action => 'action')
|
97
97
|
|
98
98
|
response = @route_set.recognize(build_request({:method => 'get', :path => '/path/'}))
|
@@ -101,7 +101,7 @@ describe "Usher route recognition" do
|
|
101
101
|
|
102
102
|
it "should recognize a format-style variable" do
|
103
103
|
target_route = @route_set.add_route('/sample.:format', :controller => 'sample', :action => 'action')
|
104
|
-
@route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [
|
104
|
+
@route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, ['html'], nil, "/sample.html")
|
105
105
|
end
|
106
106
|
|
107
107
|
it "should recognize a glob-style variable" do
|
@@ -236,12 +236,12 @@ describe "Usher route recognition" do
|
|
236
236
|
|
237
237
|
it "should recognize a format-style literal" do
|
238
238
|
target_route = @route_set.add_route('/:action.html', :controller => 'sample', :action => 'action')
|
239
|
-
@route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [
|
239
|
+
@route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, ['sample'], nil, "/sample.html")
|
240
240
|
end
|
241
241
|
|
242
242
|
it "should recognize a format-style variable along side another variable" do
|
243
243
|
target_route = @route_set.add_route('/:action.:format', :controller => 'sample', :action => 'action')
|
244
|
-
@route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [
|
244
|
+
@route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, ['sample', 'html'], nil, '/sample.html')
|
245
245
|
end
|
246
246
|
|
247
247
|
it "should use a requirement (proc) on incoming variables" do
|
@@ -336,7 +336,11 @@ describe "Usher route recognition" do
|
|
336
336
|
it "should partially match a route" do
|
337
337
|
route = @route_set.add_route("/foo")
|
338
338
|
route.match_partially!
|
339
|
-
@route_set.recognize(build_request(:method => "get", :path => "/foo/bar"))
|
339
|
+
response = @route_set.recognize(build_request(:method => "get", :path => "/foo/bar"))
|
340
|
+
response.partial_match?.should be_true
|
341
|
+
response.params.should == []
|
342
|
+
response.remaining_path.should == '/bar'
|
343
|
+
response.matched_path.should == '/foo'
|
340
344
|
end
|
341
345
|
|
342
346
|
it "should partially match a route and use request conditions" do
|
@@ -401,5 +405,5 @@ describe "Usher route recognition" do
|
|
401
405
|
end
|
402
406
|
|
403
407
|
end
|
404
|
-
|
408
|
+
|
405
409
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: usher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Neighman
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-01-
|
17
|
+
date: 2010-01-12 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -27,7 +27,7 @@ dependencies:
|
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: 0.0.11
|
29
29
|
version:
|
30
|
-
description:
|
30
|
+
description: Pure ruby general purpose router with interfaces for rails, rack, email or choose your own adventure
|
31
31
|
email: joshbuddy@gmail.com
|
32
32
|
executables: []
|
33
33
|
|
@@ -60,6 +60,8 @@ files:
|
|
60
60
|
- lib/usher/interface/sinatra.rb
|
61
61
|
- lib/usher/interface/text.rb
|
62
62
|
- lib/usher/node.rb
|
63
|
+
- lib/usher/node/response.rb
|
64
|
+
- lib/usher/node/root.rb
|
63
65
|
- lib/usher/route.rb
|
64
66
|
- lib/usher/route/path.rb
|
65
67
|
- lib/usher/route/request_method.rb
|
@@ -70,6 +72,7 @@ files:
|
|
70
72
|
- lib/usher/util.rb
|
71
73
|
- lib/usher/util/generate.rb
|
72
74
|
- lib/usher/util/graph.rb
|
75
|
+
- lib/usher/util/mapper.rb
|
73
76
|
- lib/usher/util/parser.rb
|
74
77
|
- lib/usher/util/rack-mixins.rb
|
75
78
|
- rails/init.rb
|
@@ -125,7 +128,7 @@ rubyforge_project: joshbuddy-usher
|
|
125
128
|
rubygems_version: 1.3.5
|
126
129
|
signing_key:
|
127
130
|
specification_version: 3
|
128
|
-
summary:
|
131
|
+
summary: Pure ruby general purpose router with interfaces for rails, rack, email or choose your own adventure
|
129
132
|
test_files:
|
130
133
|
- spec/private/delimiters_spec.rb
|
131
134
|
- spec/private/destination_spec.rb
|