usher 0.4.8 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +12 -1
- data/Rakefile +5 -29
- data/VERSION.yml +2 -2
- data/lib/usher.rb +126 -37
- data/lib/usher/grapher.rb +5 -4
- data/lib/usher/interface.rb +12 -5
- data/lib/usher/interface/email_interface.rb +1 -1
- data/lib/usher/interface/rack_interface.rb +31 -13
- data/lib/usher/interface/rails2_2_interface.rb +3 -4
- data/lib/usher/interface/rails2_3_interface.rb +3 -4
- data/lib/usher/interface/rails3_interface.rb +57 -0
- data/lib/usher/node.rb +121 -73
- data/lib/usher/route.rb +45 -11
- data/lib/usher/route/path.rb +50 -11
- data/lib/usher/route/util.rb +65 -0
- data/lib/usher/route/variable.rb +22 -11
- data/lib/usher/splitter.rb +4 -141
- data/lib/usher/util.rb +6 -0
- data/lib/usher/util/generate.rb +129 -0
- data/lib/usher/util/parser.rb +145 -0
- data/spec/private/email/recognize_spec.rb +2 -4
- data/spec/private/generate_spec.rb +86 -32
- data/spec/private/grapher_spec.rb +5 -6
- data/spec/private/parser_spec.rb +75 -0
- data/spec/private/path_spec.rb +35 -4
- data/spec/private/rack/dispatch_spec.rb +100 -15
- data/spec/private/recognize_spec.rb +88 -50
- data/spec/spec_helper.rb +22 -0
- metadata +13 -7
- data/lib/usher/generate.rb +0 -131
- data/spec/private/split_spec.rb +0 -76
data/lib/usher/generate.rb
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
require 'rack'
|
2
|
-
|
3
|
-
unless Rack::Utils.respond_to?(:uri_escape)
|
4
|
-
module Rack
|
5
|
-
|
6
|
-
module Utils
|
7
|
-
|
8
|
-
def uri_escape(s)
|
9
|
-
s.to_s.gsub(/([^:\/?\[\]\-_~\.!\$&'\(\)\*\+,;=@a-zA-Z0-9]+)/n) {
|
10
|
-
'%'<<$1.unpack('H2'*$1.size).join('%').upcase
|
11
|
-
}.tr(' ', '+')
|
12
|
-
end
|
13
|
-
module_function :uri_escape
|
14
|
-
|
15
|
-
def uri_unescape(s)
|
16
|
-
gsub(/((?:%[0-9a-fA-F]{2})+)/n){
|
17
|
-
[$1.delete('%')].pack('H*')
|
18
|
-
}
|
19
|
-
end
|
20
|
-
module_function :uri_unescape
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Usher
|
27
|
-
class Generators
|
28
|
-
|
29
|
-
class URL
|
30
|
-
|
31
|
-
def initialize(usher)
|
32
|
-
@usher = usher
|
33
|
-
end
|
34
|
-
|
35
|
-
def generate_full(routing_lookup, request, params = nil)
|
36
|
-
path = path_for_routing_lookup(routing_lookup, params)
|
37
|
-
result = generate_start(path, request)
|
38
|
-
result << generate_path(path, params)
|
39
|
-
end
|
40
|
-
|
41
|
-
def generate(routing_lookup, params = nil)
|
42
|
-
generate_path(path_for_routing_lookup(routing_lookup, params), params)
|
43
|
-
end
|
44
|
-
|
45
|
-
def generate_start(path, request)
|
46
|
-
result = (path.route.generate_with && path.route.generate_with.scheme || request.scheme).dup
|
47
|
-
result << '://'
|
48
|
-
result << (path.route.generate_with && path.route.generate_with.host) ? path.route.generate_with.host : request.host
|
49
|
-
port = path.route.generate_with && path.route.generate_with.port || request.port
|
50
|
-
if result[4] == ?s
|
51
|
-
result << ':' << port.to_s if port != 443
|
52
|
-
else
|
53
|
-
result << ':' << port.to_s if port != 80
|
54
|
-
end
|
55
|
-
result
|
56
|
-
end
|
57
|
-
|
58
|
-
def path_for_routing_lookup(routing_lookup, params)
|
59
|
-
path = case routing_lookup
|
60
|
-
when Symbol
|
61
|
-
route = @usher.named_routes[routing_lookup]
|
62
|
-
params.is_a?(Hash) ? route.find_matching_path(params) : route.paths.first
|
63
|
-
when Route
|
64
|
-
params.is_a?(Hash) ? routing_lookup.find_matching_path(params) : routing_lookup.paths.first
|
65
|
-
when nil
|
66
|
-
params.is_a?(Hash) ? @usher.path_for_options(params) : raise
|
67
|
-
when Route::Path
|
68
|
-
routing_lookup
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# Generates a completed URL based on a +route+ or set of optional +params+
|
73
|
-
#
|
74
|
-
# set = Usher.new
|
75
|
-
# route = set.add_named_route(:test_route, '/:controller/:action')
|
76
|
-
# set.generate_url(nil, {:controller => 'c', :action => 'a'}) == '/c/a' => true
|
77
|
-
# set.generate_url(:test_route, {:controller => 'c', :action => 'a'}) == '/c/a' => true
|
78
|
-
# set.generate_url(route.primary_path, {:controller => 'c', :action => 'a'}) == '/c/a' => true
|
79
|
-
def generate_path(path, params = nil)
|
80
|
-
raise UnrecognizedException.new unless path
|
81
|
-
|
82
|
-
params = Array(params) if params.is_a?(String)
|
83
|
-
if params.is_a?(Array)
|
84
|
-
given_size = params.size
|
85
|
-
extra_params = params.last.is_a?(Hash) ? params.pop : nil
|
86
|
-
params = Hash[*path.dynamic_parts.inject([]){|a, dynamic_part| a.concat([dynamic_part.name, params.shift || raise(MissingParameterException.new("got #{given_size}, expected #{path.dynamic_parts.size} parameters"))]); a}]
|
87
|
-
params.merge!(extra_params) if extra_params
|
88
|
-
end
|
89
|
-
|
90
|
-
result = ''
|
91
|
-
path.parts.each do |part|
|
92
|
-
case part
|
93
|
-
when Route::Variable
|
94
|
-
value = (params && params.delete(part.name)) || part.default_value || raise(MissingParameterException.new)
|
95
|
-
case part.type
|
96
|
-
when :*
|
97
|
-
value.each_with_index do |current_value, index|
|
98
|
-
current_value = current_value.to_s unless current_value.is_a?(String)
|
99
|
-
part.valid!(current_value)
|
100
|
-
result << current_value
|
101
|
-
result << '/' if index != value.size - 1
|
102
|
-
end
|
103
|
-
when :':'
|
104
|
-
value = value.to_s unless value.is_a?(String)
|
105
|
-
part.valid!(value)
|
106
|
-
result << value
|
107
|
-
end
|
108
|
-
else
|
109
|
-
result << part
|
110
|
-
end
|
111
|
-
end
|
112
|
-
result = Rack::Utils.uri_escape(result)
|
113
|
-
|
114
|
-
if params && !params.empty?
|
115
|
-
has_query = result[??]
|
116
|
-
params.each do |k,v|
|
117
|
-
case v
|
118
|
-
when Array
|
119
|
-
v.each do |v_part|
|
120
|
-
result << (has_query ? '&' : has_query = true && '?') << Rack::Utils.escape("#{k.to_s}[]") << '=' << Rack::Utils.escape(v_part.to_s)
|
121
|
-
end
|
122
|
-
else
|
123
|
-
result << (has_query ? '&' : has_query = true && '?') << Rack::Utils.escape(k.to_s) << '=' << Rack::Utils.escape(v.to_s)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
result
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
data/spec/private/split_spec.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'lib/usher'
|
2
|
-
|
3
|
-
describe "Usher route tokenizing" do
|
4
|
-
|
5
|
-
|
6
|
-
it "should split / delimited routes" do
|
7
|
-
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this/split').should == [['/', 'test', '/','this', '/', 'split']]
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should split / delimited routes with a regex in it" do
|
11
|
-
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').
|
12
|
-
split('/test/{this}/split').should == [['/', 'test', '/', /this/, '/', 'split']]
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should split on ' ' delimited routes as well" do
|
16
|
-
Usher::Splitter.for_delimiters([' '], '[0-9A-Za-z\$\-_\+!\*\',]+').split('test this split').should == [['test', ' ', 'this', ' ', 'split']]
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should split on email delimiters as well" do
|
20
|
-
Usher::Splitter.for_delimiters(['@', '+', '-', '.'], '[a-zA-Z0-9]+').split('one+more.12345-09876-alphanum3ric5@domain.com').should == [["one", '+', "more", ".", "12345", '-', "09876", '-', "alphanum3ric5", "@", "domain", ".", "com"]]
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should split on ' ' delimited routes for more complex routes as well" do
|
24
|
-
Usher::Splitter.for_delimiters([' '], '[0-9A-Za-z\$\-_\+!\*\',]+').split('(test|this) split').should == [['test', ' ', 'split'], ['this', ' ', 'split']]
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should group optional parts with brackets" do
|
28
|
-
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split)').should == [
|
29
|
-
['/', 'test', '/', 'this'],
|
30
|
-
['/', 'test', '/', 'this', '/', 'split']
|
31
|
-
]
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should group exclusive optional parts with brackets and pipes" do
|
35
|
-
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split|/split2)').should == [
|
36
|
-
['/', 'test', '/', 'this','/', 'split'],
|
37
|
-
['/', 'test', '/', 'this','/', 'split2']
|
38
|
-
]
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should group exclusive optional-optional parts with brackets and pipes" do
|
42
|
-
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this((/split|/split2))').should == [
|
43
|
-
['/', 'test','/', 'this'],
|
44
|
-
['/', 'test','/', 'this', '/', 'split'],
|
45
|
-
['/', 'test','/', 'this', '/', 'split2']
|
46
|
-
]
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should group optional parts with brackets (for non overlapping groups)" do
|
50
|
-
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split)(/split2)') == [
|
51
|
-
['/', "test", '/', "this"],
|
52
|
-
['/', "test", '/', "this", '/', "split"],
|
53
|
-
['/', "test", '/', "this", '/', "split2"],
|
54
|
-
['/', "test", '/', "this", '/', "split", '/', "split2"]
|
55
|
-
]
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should group nested-optional parts with brackets" do
|
59
|
-
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split(.:format))') == [
|
60
|
-
['/', "test", '/', "this"],
|
61
|
-
['/', "test", '/', "this", '/', "split"],
|
62
|
-
['/', "test", '/', "this", '/', "split", '.', Usher::Route::Variable.new(:':', :format)]
|
63
|
-
]
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should to_s all different variable types" do
|
67
|
-
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/:split/*splitter').first.collect{|v| v.to_s} ==
|
68
|
-
[ ':split', '*splitter' ]
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should == variable types" do
|
72
|
-
parts = Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/:split/:split').first
|
73
|
-
parts[1].should == parts[3]
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|