usher 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|