usher 0.7.1 → 0.7.2
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/Gemfile +10 -0
- data/README.markdown +158 -0
- data/Rakefile +47 -12
- data/benchmarks/rack_recognition_bm.rb +48 -0
- data/lib/usher/delimiters.rb +20 -8
- data/lib/usher/exceptions.rb +4 -0
- data/lib/usher/grapher.rb +38 -32
- data/lib/usher/interface/rack/builder.rb +39 -0
- data/lib/usher/interface/rack/middleware.rb +22 -0
- data/lib/usher/interface/rack.rb +6 -55
- data/lib/usher/interface/sinatra.rb +115 -56
- data/lib/usher/interface.rb +12 -22
- data/lib/usher/node/response.rb +3 -1
- data/lib/usher/node.rb +56 -75
- data/lib/usher/route/static.rb +2 -0
- data/lib/usher/route/variable.rb +1 -1
- data/lib/usher/route.rb +21 -18
- data/lib/usher/splitter.rb +4 -6
- data/lib/usher/util/generate.rb +50 -34
- data/lib/usher/util/parser.rb +12 -9
- data/lib/usher.rb +204 -162
- data/spec/private/generate_spec.rb +5 -0
- data/spec/private/recognize_spec.rb +12 -12
- data/spec/private/sinatra/recognize_spec.rb +102 -0
- data/spec/spec_helper.rb +1 -1
- data/usher.gemspec +8 -5
- metadata +75 -19
- data/README.rdoc +0 -158
- data/spec/rails2_2/compat.rb +0 -3
- data/spec/rails2_2/generate_spec.rb +0 -28
- data/spec/rails2_2/path_spec.rb +0 -16
- data/spec/rails2_2/recognize_spec.rb +0 -78
- data/spec/rails2_3/compat.rb +0 -2
- data/spec/rails2_3/generate_spec.rb +0 -28
- data/spec/rails2_3/path_spec.rb +0 -16
- data/spec/rails2_3/recognize_spec.rb +0 -78
@@ -1,66 +1,125 @@
|
|
1
1
|
class Usher
|
2
2
|
module Interface
|
3
3
|
class Sinatra
|
4
|
-
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
::Sinatra.send(:include, Extension)
|
7
|
+
end
|
8
|
+
|
5
9
|
module Extension
|
6
|
-
|
7
|
-
def self.included(cls)
|
8
|
-
cls::Base.class_eval(<<-HERE_DOC, __FILE__, __LINE__)
|
9
|
-
def self.route(verb, path, options={}, &block)
|
10
|
-
@router ||= Usher.new(:request_methods => [:request_method, :host, :port, :scheme], :generator => Usher::Util::Generators::URL.new)
|
11
|
-
|
12
|
-
name = options.delete(:name)
|
13
|
-
options[:conditions] ||= {}
|
14
|
-
options[:conditions][:request_method] = verb
|
15
|
-
options[:conditions][:host] = options.delete(:host) if options.key?(:host)
|
16
|
-
|
17
|
-
# Because of self.options.host
|
18
|
-
host_name(options.delete(:host)) if options.key?(:host)
|
19
|
-
|
20
|
-
define_method "\#{verb} \#{path}", &block
|
21
|
-
unbound_method = instance_method("\#{verb} \#{path}")
|
22
|
-
block =
|
23
|
-
if block.arity != 0
|
24
|
-
lambda { unbound_method.bind(self).call(*@block_params) }
|
25
|
-
else
|
26
|
-
lambda { unbound_method.bind(self).call }
|
27
|
-
end
|
28
|
-
|
29
|
-
invoke_hook(:route_added, verb, path, block)
|
30
|
-
|
31
|
-
route = @router.add_route(path, options).to(block)
|
32
|
-
route.name(name) if name
|
33
|
-
route
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.router
|
37
|
-
@router
|
38
|
-
end
|
39
10
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
11
|
+
def self.registered(app)
|
12
|
+
app.send(:include, Extension)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.included(base)
|
16
|
+
base.extend ClassMethods
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate(name, *params)
|
20
|
+
self.class.generate(name, *params)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def route!(base=self.class, pass_block=nil)
|
25
|
+
if base.router and match = base.router.recognize(@request, @request.path_info)
|
26
|
+
@block_params = match.params.map { |p| p.last }
|
27
|
+
(@params ||= {}).merge!(match.params_as_hash)
|
28
|
+
pass_block = catch(:pass) do
|
44
29
|
route_eval(&match.destination)
|
45
|
-
elsif base.superclass.respond_to?(:routes)
|
46
|
-
route! base.superclass
|
47
|
-
else
|
48
|
-
route_missing
|
49
30
|
end
|
50
31
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
32
|
+
|
33
|
+
# Run routes defined in superclass.
|
34
|
+
if base.superclass.respond_to?(:router)
|
35
|
+
route! base.superclass, pass_block
|
36
|
+
return
|
54
37
|
end
|
55
38
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
39
|
+
route_eval(&pass_block) if pass_block
|
40
|
+
|
41
|
+
route_missing
|
42
|
+
end
|
43
|
+
|
44
|
+
module ClassMethods
|
45
|
+
|
46
|
+
def new(*args, &bk)
|
47
|
+
configure! unless @_configured
|
48
|
+
super(*args, &bk)
|
49
|
+
end
|
50
|
+
|
51
|
+
def route(verb, path, options={}, &block)
|
52
|
+
path.gsub!(/\/\?$/, "(/)")
|
53
|
+
name = options.delete(:name)
|
54
|
+
options[:conditions] ||= {}
|
55
|
+
options[:conditions][:request_method] = verb
|
56
|
+
options[:conditions][:host] = options.delete(:host) if options.key?(:host)
|
57
|
+
|
58
|
+
define_method "#{verb} #{path}", &block
|
59
|
+
unbound_method = instance_method("#{verb} #{path}")
|
60
|
+
block =
|
61
|
+
if block.arity != 0
|
62
|
+
lambda { unbound_method.bind(self).call(*@block_params) }
|
63
|
+
else
|
64
|
+
lambda { unbound_method.bind(self).call }
|
65
|
+
end
|
66
|
+
|
67
|
+
invoke_hook(:route_added, verb, path, block)
|
68
|
+
|
69
|
+
route = router.add_route(path, options).to(block)
|
70
|
+
route.name(name) if name
|
71
|
+
route
|
72
|
+
end
|
73
|
+
|
74
|
+
def router
|
75
|
+
@router ||= Usher.new(:request_methods => [:request_method, :host, :port, :scheme],
|
76
|
+
:ignore_trailing_delimiters => true,
|
77
|
+
:generator => Usher::Util::Generators::URL.new,
|
78
|
+
:delimiters => ['/', '.', '-'],
|
79
|
+
:valid_regex => '[0-9A-Za-z\$_\+!\*\',]+')
|
80
|
+
block_given? ? yield(@router) : @router
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate(name, *params)
|
84
|
+
router.generator.generate(name, *params)
|
85
|
+
end
|
86
|
+
|
87
|
+
def reset!
|
88
|
+
router.reset!
|
89
|
+
super
|
90
|
+
end
|
91
|
+
|
92
|
+
def configure!
|
93
|
+
configure :development do
|
94
|
+
error 404 do
|
95
|
+
content_type 'text/html'
|
96
|
+
|
97
|
+
(<<-HTML).gsub(/^ {17}/, '')
|
98
|
+
<!DOCTYPE html>
|
99
|
+
<html>
|
100
|
+
<head>
|
101
|
+
<style type="text/css">
|
102
|
+
body { text-align:center;font-family:helvetica,arial;font-size:22px;
|
103
|
+
color:#888;margin:20px}
|
104
|
+
#c {margin:0 auto;width:500px;text-align:left}
|
105
|
+
</style>
|
106
|
+
</head>
|
107
|
+
<body>
|
108
|
+
<h2>Sinatra doesn't know this ditty.</h2>
|
109
|
+
<div id="c">
|
110
|
+
Try this:
|
111
|
+
<pre>#{request.request_method.downcase} '#{request.path_info}' do\n "Hello World"\nend</pre>
|
112
|
+
</div>
|
113
|
+
</body>
|
114
|
+
</html>
|
115
|
+
HTML
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
@_configured = true
|
120
|
+
end
|
121
|
+
end # ClassMethods
|
122
|
+
end # Extension
|
123
|
+
end # Sinatra
|
124
|
+
end # Interface
|
125
|
+
end # Usher
|
data/lib/usher/interface.rb
CHANGED
@@ -1,30 +1,20 @@
|
|
1
1
|
class Usher
|
2
|
+
# Various interfaces for Usher.
|
2
3
|
module Interface
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
register(:rails22, File.join(File.dirname(__FILE__), 'interface', 'rails22'))
|
14
|
-
register(:rails23, File.join(File.dirname(__FILE__), 'interface', 'rails23'))
|
15
|
-
register(:rack, File.join(File.dirname(__FILE__), 'interface', 'rack'))
|
16
|
-
register(:rails3, File.join(File.dirname(__FILE__), 'interface', 'rails3'))
|
17
|
-
register(:text, File.join(File.dirname(__FILE__), 'interface', 'text'))
|
18
|
-
register(:sinatra, File.join(File.dirname(__FILE__), 'interface', 'sinatra'))
|
5
|
+
autoload(:Email, File.join(File.dirname(__FILE__), 'interface', 'email'))
|
6
|
+
autoload(:Merb, File.join(File.dirname(__FILE__), 'interface', 'merb'))
|
7
|
+
autoload(:Rails20, File.join(File.dirname(__FILE__), 'interface', 'rails20'))
|
8
|
+
autoload(:Rails22, File.join(File.dirname(__FILE__), 'interface', 'rails22'))
|
9
|
+
autoload(:Rails23, File.join(File.dirname(__FILE__), 'interface', 'rails23'))
|
10
|
+
autoload(:Rack, File.join(File.dirname(__FILE__), 'interface', 'rack'))
|
11
|
+
autoload(:Rails3, File.join(File.dirname(__FILE__), 'interface', 'rails3'))
|
12
|
+
autoload(:Text, File.join(File.dirname(__FILE__), 'interface', 'text'))
|
13
|
+
autoload(:Sinatra, File.join(File.dirname(__FILE__), 'interface', 'sinatra'))
|
19
14
|
|
20
15
|
def self.class_for(name)
|
21
|
-
name
|
22
|
-
|
23
|
-
require InterfaceRegistry[name]
|
24
|
-
Usher::Interface.const_get(File.basename(InterfaceRegistry[name]).to_s.split(/_/).map{|e| e.capitalize}.join)
|
25
|
-
else
|
26
|
-
raise ArgumentError, "Interface #{name.inspect} doesn't exist. Choose one of: #{InterfaceRegistry.keys.inspect}"
|
27
|
-
end
|
16
|
+
Usher::Interface.const_get(name.to_s.split(/_/).map{|e| e.capitalize}.join) or
|
17
|
+
raise ArgumentError, "Interface #{name.inspect} doesn't exist."
|
28
18
|
end
|
29
19
|
|
30
20
|
# Usher::Interface.for(:rack, &block)
|
data/lib/usher/node/response.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
class Usher
|
2
2
|
class Node
|
3
|
-
class Response < Struct.new(:path, :params_as_array, :remaining_path, :matched_path
|
3
|
+
class Response < Struct.new(:path, :params_as_array, :remaining_path, :matched_path)
|
4
4
|
|
5
|
+
attr_accessor :only_trailing_delimiters
|
6
|
+
|
5
7
|
def params
|
6
8
|
@params ||= path.convert_params_array(params_as_array)
|
7
9
|
end
|
data/lib/usher/node.rb
CHANGED
@@ -9,44 +9,12 @@ class Usher
|
|
9
9
|
|
10
10
|
def initialize(parent, value)
|
11
11
|
@parent, @value = parent, value
|
12
|
-
@request = nil
|
13
|
-
@normal = nil
|
14
|
-
@greedy = nil
|
15
|
-
@request_method_type = nil
|
16
|
-
end
|
17
|
-
|
18
|
-
def activate_normal!
|
19
|
-
@normal ||= Hash.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def activate_greedy!
|
23
|
-
@greedy ||= Hash.new
|
24
|
-
end
|
25
|
-
|
26
|
-
def activate_request!
|
27
|
-
@request ||= Hash.new
|
28
|
-
end
|
29
|
-
|
30
|
-
def upgrade_normal!
|
31
|
-
@normal = FuzzyHash.new(@normal)
|
32
|
-
end
|
33
|
-
|
34
|
-
def upgrade_greedy!
|
35
|
-
@greedy = FuzzyHash.new(@greedy)
|
36
|
-
end
|
37
|
-
|
38
|
-
def upgrade_request!
|
39
|
-
@request = FuzzyHash.new(@request)
|
40
12
|
end
|
41
13
|
|
42
14
|
def depth
|
43
15
|
@depth ||= parent.is_a?(Node) ? parent.depth + 1 : 0
|
44
16
|
end
|
45
17
|
|
46
|
-
def greedy?
|
47
|
-
@greedy
|
48
|
-
end
|
49
|
-
|
50
18
|
def terminates?
|
51
19
|
@terminates && @terminates.route.recognizable?
|
52
20
|
end
|
@@ -66,68 +34,57 @@ class Usher
|
|
66
34
|
def root
|
67
35
|
@root ||= ancestors.last
|
68
36
|
end
|
69
|
-
|
37
|
+
|
70
38
|
def route_set
|
71
39
|
@route_set ||= root.route_set
|
72
40
|
end
|
73
41
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
$stdout << "g #{k.inspect} ==> \n"
|
85
|
-
v.pp
|
86
|
-
end if greedy
|
87
|
-
request.each do |k,v|
|
88
|
-
$stdout << " " * (depth + 1)
|
89
|
-
$stdout << "r #{k.inspect} ==> \n"
|
90
|
-
v.pp
|
91
|
-
end if request
|
42
|
+
def inspect
|
43
|
+
out = ''
|
44
|
+
out << " " * depth
|
45
|
+
out << "#{terminates? ? '* ' : ''}#{depth}: #{value.inspect}\n"
|
46
|
+
[:normal, :greedy, :request].each do |node_type|
|
47
|
+
send(node_type).each do |k,v|
|
48
|
+
out << (" " * (depth + 1)) << "#{node_type.to_s[0].chr} #{k.inspect} ==> \n" << v.inspect
|
49
|
+
end if send(node_type)
|
50
|
+
end
|
51
|
+
out
|
92
52
|
end
|
93
53
|
|
94
54
|
def find(request_object, original_path, path, params = [])
|
95
55
|
# terminates or is partial
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
Response.new(terminates, params,
|
56
|
+
|
57
|
+
if terminates? && (path.empty? || terminates.route.partial_match?)
|
58
|
+
response = terminates.route.partial_match? ?
|
59
|
+
Response.new(terminates, params, path.join, original_path[0, original_path.size - path.join.size]) :
|
60
|
+
Response.new(terminates, params, nil, original_path)
|
100
61
|
# terminates or is partial
|
101
|
-
elsif
|
102
|
-
|
62
|
+
elsif !path.empty? and greedy and match_with_result_output = greedy.match_with_result(whole_path = path.join)
|
63
|
+
child_node, matched_part = match_with_result_output
|
103
64
|
whole_path.slice!(0, matched_part.size)
|
104
|
-
params << matched_part if
|
105
|
-
|
106
|
-
elsif
|
65
|
+
params << matched_part if child_node.value.is_a?(Route::Variable)
|
66
|
+
child_node.find(request_object, original_path, whole_path.empty? ? whole_path : route_set.splitter.split(whole_path), params)
|
67
|
+
elsif !path.empty? and normal and child_node = normal[path.first] || normal[nil]
|
107
68
|
part = path.shift
|
108
|
-
case
|
69
|
+
case child_node.value
|
109
70
|
when String
|
110
71
|
when Route::Variable::Single
|
111
|
-
variable =
|
112
|
-
variable.valid!(part)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end
|
118
|
-
end
|
72
|
+
variable = child_node.value # get the variable
|
73
|
+
variable.valid!(part) # do a validity check
|
74
|
+
until path.empty? || (variable.look_ahead === path.first) # variables have a look ahead notion,
|
75
|
+
next_path_part = path.shift # and until they are satified,
|
76
|
+
part << next_path_part
|
77
|
+
end if variable.look_ahead
|
119
78
|
params << part # because its a variable, we need to add it to the params array
|
120
79
|
when Route::Variable::Glob
|
121
80
|
params << []
|
122
81
|
loop do
|
123
|
-
if (
|
82
|
+
if (child_node.value.look_ahead === part || (!route_set.delimiters.unescaped.include?(part) && child_node.value.regex_matcher && !child_node.value.regex_matcher.match(part)))
|
124
83
|
path.unshift(part)
|
125
|
-
if route_set.delimiters.unescaped.include?(
|
126
|
-
path.unshift(next_part.parent.value)
|
127
|
-
end
|
84
|
+
path.unshift(child_node.parent.value) if route_set.delimiters.unescaped.include?(child_node.parent.value)
|
128
85
|
break
|
129
86
|
elsif !route_set.delimiters.unescaped.include?(part)
|
130
|
-
|
87
|
+
child_node.value.valid!(part)
|
131
88
|
params.last << part
|
132
89
|
end
|
133
90
|
unless part = path.shift
|
@@ -135,7 +92,7 @@ class Usher
|
|
135
92
|
end
|
136
93
|
end
|
137
94
|
end
|
138
|
-
|
95
|
+
child_node.find(request_object, original_path, path, params)
|
139
96
|
elsif request_method_type
|
140
97
|
if route_set.priority_lookups?
|
141
98
|
route_candidates = []
|
@@ -159,5 +116,29 @@ class Usher
|
|
159
116
|
end
|
160
117
|
end
|
161
118
|
|
119
|
+
def activate_normal!
|
120
|
+
@normal ||= {}
|
121
|
+
end
|
122
|
+
|
123
|
+
def activate_greedy!
|
124
|
+
@greedy ||= {}
|
125
|
+
end
|
126
|
+
|
127
|
+
def activate_request!
|
128
|
+
@request ||= {}
|
129
|
+
end
|
130
|
+
|
131
|
+
def upgrade_normal!
|
132
|
+
@normal = FuzzyHash.new(@normal)
|
133
|
+
end
|
134
|
+
|
135
|
+
def upgrade_greedy!
|
136
|
+
@greedy = FuzzyHash.new(@greedy)
|
137
|
+
end
|
138
|
+
|
139
|
+
def upgrade_request!
|
140
|
+
@request = FuzzyHash.new(@request)
|
141
|
+
end
|
142
|
+
|
162
143
|
end
|
163
144
|
end
|
data/lib/usher/route/static.rb
CHANGED
data/lib/usher/route/variable.rb
CHANGED
@@ -14,7 +14,7 @@ class Usher
|
|
14
14
|
|
15
15
|
module CaseEqualsValidator
|
16
16
|
def valid!(val)
|
17
|
-
@validator === val or raise(ValidationException.new("#{val} does not conform to #{@validator}"))
|
17
|
+
@validator === val.to_s or raise(ValidationException.new("#{val} does not conform to #{@validator}"))
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/lib/usher/route.rb
CHANGED
@@ -50,12 +50,12 @@ class Usher
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def unrecognizable!
|
53
|
-
|
53
|
+
@recognizable = false
|
54
54
|
self
|
55
55
|
end
|
56
56
|
|
57
57
|
def recognizable!
|
58
|
-
|
58
|
+
@recognizable = true
|
59
59
|
self
|
60
60
|
end
|
61
61
|
|
@@ -93,17 +93,18 @@ class Usher
|
|
93
93
|
|
94
94
|
CompoundDestination = Struct.new(:args, :block, :options)
|
95
95
|
|
96
|
-
# Sets destination on a route.
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
96
|
+
# Sets destination on a route.
|
97
|
+
# @return [self]
|
98
|
+
# @param [Object] args
|
99
|
+
# If you pass in more than one variable, it will be returned to you wrapped in a {CompoundDestination}
|
100
|
+
# If you send it varargs and the last member is a Hash, it will pop off the hash, and will be stored under {CompoundDestination#options}
|
101
|
+
# Otherwise, if you use send a single variable, or call it with a block, these will be returned to you by {CompoundDestination#destination}
|
102
|
+
# @example
|
103
|
+
# Request = Struct.new(:path)
|
104
|
+
# set = Usher.new
|
105
|
+
# route = set.add_route('/test')
|
106
|
+
# route.to(:controller => 'testing', :action => 'index')
|
107
|
+
# set.recognize(Request.new('/test')).first.params => {:controller => 'testing', :action => 'index'}
|
107
108
|
#
|
108
109
|
#
|
109
110
|
#
|
@@ -126,11 +127,13 @@ class Usher
|
|
126
127
|
self
|
127
128
|
end
|
128
129
|
|
129
|
-
# Sets route as referenceable from
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
130
|
+
# Sets route as referenceable from `name`
|
131
|
+
# @param [Symbol] name The name of the route
|
132
|
+
# @return [self] The route named
|
133
|
+
# @example
|
134
|
+
# set = Usher.new
|
135
|
+
# route = set.add_route('/test').name(:route)
|
136
|
+
# set.generate_url(:route) => '/test'
|
134
137
|
def name(name)
|
135
138
|
@named = name
|
136
139
|
@router.name(name, self)
|
data/lib/usher/splitter.rb
CHANGED
@@ -3,21 +3,19 @@ class Usher
|
|
3
3
|
|
4
4
|
def self.for_delimiters(delimiters_array)
|
5
5
|
delimiters = Delimiters.new(delimiters_array)
|
6
|
-
|
6
|
+
delimiters.any?{|d| d.size > 1} ?
|
7
7
|
MultiCharacterSplitterInstance.new(delimiters) :
|
8
8
|
SingleCharacterSplitterInstance.new(delimiters)
|
9
9
|
end
|
10
10
|
|
11
11
|
class SingleCharacterSplitterInstance
|
12
12
|
|
13
|
-
attr_reader :url_split_regex
|
14
|
-
|
15
13
|
def initialize(delimiters)
|
16
|
-
@url_split_regex = Regexp.new("[^#{delimiters.
|
14
|
+
@url_split_regex = Regexp.new("[^#{delimiters.regexp_char_class}]+|[#{delimiters.regexp_char_class}]")
|
17
15
|
end
|
18
16
|
|
19
17
|
def split(path)
|
20
|
-
path.scan(url_split_regex)
|
18
|
+
path.scan(@url_split_regex)
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
@@ -36,7 +34,7 @@ class Usher
|
|
36
34
|
protected
|
37
35
|
|
38
36
|
def delimiters_regexp
|
39
|
-
|
37
|
+
@delimiters.regexp
|
40
38
|
end
|
41
39
|
|
42
40
|
end
|
data/lib/usher/util/generate.rb
CHANGED
@@ -12,45 +12,61 @@ class Usher
|
|
12
12
|
|
13
13
|
def generate_path_for_base_params(path, params)
|
14
14
|
raise UnrecognizedException.new unless path
|
15
|
-
result = ''
|
16
|
-
|
17
15
|
case params
|
18
16
|
when nil, Hash
|
19
|
-
path
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
17
|
+
generate_path_for_base_params_with_hash(path, params)
|
18
|
+
else
|
19
|
+
generate_path_for_base_params_with_array(path, Array(params))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate_path_for_base_params_with_hash(path, params)
|
24
|
+
result = ''
|
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
|
34
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
|
35
44
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
result << value.to_s
|
45
|
+
end
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def generate_path_for_base_params_with_array(path, params)
|
50
|
+
result = ''
|
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
|
53
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
|
54
70
|
end
|
55
71
|
end
|
56
72
|
result
|