rack-mount 0.0.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +12 -4
- data/lib/rack/mount/analysis/histogram.rb +55 -6
- data/lib/rack/mount/analysis/splitting.rb +103 -89
- data/lib/rack/mount/code_generation.rb +120 -0
- data/lib/rack/mount/generatable_regexp.rb +95 -48
- data/lib/rack/mount/multimap.rb +84 -41
- data/lib/rack/mount/prefix.rb +13 -8
- data/lib/rack/mount/regexp_with_named_groups.rb +27 -7
- data/lib/rack/mount/route.rb +75 -18
- data/lib/rack/mount/route_set.rb +308 -22
- data/lib/rack/mount/strexp/parser.rb +160 -0
- data/lib/rack/mount/strexp/tokenizer.rb +83 -0
- data/lib/rack/mount/strexp.rb +54 -79
- data/lib/rack/mount/utils.rb +65 -174
- data/lib/rack/mount/vendor/regin/regin/alternation.rb +40 -0
- data/lib/rack/mount/vendor/regin/regin/anchor.rb +4 -0
- data/lib/rack/mount/vendor/regin/regin/atom.rb +54 -0
- data/lib/rack/mount/vendor/regin/regin/character.rb +51 -0
- data/lib/rack/mount/vendor/regin/regin/character_class.rb +50 -0
- data/lib/rack/mount/vendor/regin/regin/collection.rb +77 -0
- data/lib/rack/mount/vendor/regin/regin/expression.rb +126 -0
- data/lib/rack/mount/vendor/regin/regin/group.rb +90 -0
- data/lib/rack/mount/vendor/regin/regin/options.rb +55 -0
- data/lib/rack/mount/vendor/regin/regin/parser.rb +546 -0
- data/lib/rack/mount/vendor/regin/regin/tokenizer.rb +255 -0
- data/lib/rack/mount/vendor/regin/regin/version.rb +3 -0
- data/lib/rack/mount/vendor/regin/regin.rb +75 -0
- data/lib/rack/mount/version.rb +3 -0
- data/lib/rack/mount.rb +13 -17
- metadata +88 -35
- data/lib/rack/mount/analysis/frequency.rb +0 -51
- data/lib/rack/mount/const.rb +0 -45
- data/lib/rack/mount/exceptions.rb +0 -3
- data/lib/rack/mount/generation/route.rb +0 -57
- data/lib/rack/mount/generation/route_set.rb +0 -163
- data/lib/rack/mount/meta_method.rb +0 -104
- data/lib/rack/mount/mixover.rb +0 -47
- data/lib/rack/mount/recognition/code_generation.rb +0 -99
- data/lib/rack/mount/recognition/route.rb +0 -59
- data/lib/rack/mount/recognition/route_set.rb +0 -88
- data/lib/rack/mount/vendor/multimap/multimap.rb +0 -466
- data/lib/rack/mount/vendor/multimap/multiset.rb +0 -153
- data/lib/rack/mount/vendor/multimap/nested_multimap.rb +0 -156
@@ -6,7 +6,7 @@ module Rack::Mount
|
|
6
6
|
attr_reader :name, :requirement
|
7
7
|
|
8
8
|
def initialize(name, requirement)
|
9
|
-
@name, @requirement = name.to_sym,
|
9
|
+
@name, @requirement = name.to_sym, requirement
|
10
10
|
freeze
|
11
11
|
end
|
12
12
|
|
@@ -25,13 +25,6 @@ module Rack::Mount
|
|
25
25
|
def inspect
|
26
26
|
"/(?<#{@name}>#{@requirement.source})/"
|
27
27
|
end
|
28
|
-
|
29
|
-
private
|
30
|
-
def bound_expression(regexp)
|
31
|
-
source, options = regexp.source, regexp.options
|
32
|
-
source = "\\A#{source}\\Z"
|
33
|
-
Regexp.compile(source, options).freeze
|
34
|
-
end
|
35
28
|
end
|
36
29
|
|
37
30
|
module InstanceMethods
|
@@ -39,20 +32,40 @@ module Rack::Mount
|
|
39
32
|
obj.segments
|
40
33
|
end
|
41
34
|
|
35
|
+
def defaults=(defaults)
|
36
|
+
@required_captures = nil
|
37
|
+
@required_params = nil
|
38
|
+
@required_defaults = nil
|
39
|
+
@defaults = defaults
|
40
|
+
end
|
41
|
+
|
42
|
+
def defaults
|
43
|
+
@defaults ||= {}
|
44
|
+
end
|
45
|
+
|
42
46
|
def generatable?
|
43
47
|
segments.any?
|
44
48
|
end
|
45
49
|
|
46
|
-
def generate(params = {}, recall = {},
|
50
|
+
def generate(params = {}, recall = {}, options = {})
|
51
|
+
return nil unless generatable?
|
52
|
+
|
47
53
|
merged = recall.merge(params)
|
48
|
-
|
54
|
+
return nil unless required_params.all? { |p| merged.include?(p) }
|
55
|
+
return nil unless required_defaults.all? { |k, v| merged[k] == v }
|
56
|
+
|
57
|
+
generate_from_segments(segments, params, merged, options)
|
49
58
|
end
|
50
59
|
|
51
60
|
def segments
|
52
61
|
@segments ||= begin
|
53
|
-
|
54
|
-
|
55
|
-
|
62
|
+
defaults
|
63
|
+
segments = []
|
64
|
+
catch(:halt) do
|
65
|
+
expression = Utils.parse_regexp(self)
|
66
|
+
segments = parse_segments(expression)
|
67
|
+
end
|
68
|
+
segments
|
56
69
|
end
|
57
70
|
end
|
58
71
|
|
@@ -61,60 +74,86 @@ module Rack::Mount
|
|
61
74
|
end
|
62
75
|
|
63
76
|
def required_captures
|
64
|
-
segments.find_all { |s|
|
77
|
+
@required_captures ||= segments.find_all { |s|
|
78
|
+
s.is_a?(DynamicSegment) && !@defaults.include?(s.name)
|
79
|
+
}.freeze
|
80
|
+
end
|
81
|
+
|
82
|
+
def required_params
|
83
|
+
@required_params ||= required_captures.map { |s| s.name }.freeze
|
84
|
+
end
|
85
|
+
|
86
|
+
def required_defaults
|
87
|
+
@required_defaults ||= begin
|
88
|
+
required_defaults = @defaults.dup
|
89
|
+
captures.inject({}) { |h, s| h.merge!(s.to_hash) }.keys.each { |name|
|
90
|
+
required_defaults.delete(name)
|
91
|
+
}
|
92
|
+
required_defaults
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def freeze
|
97
|
+
segments
|
98
|
+
captures
|
99
|
+
required_captures
|
100
|
+
required_params
|
101
|
+
required_defaults
|
102
|
+
super
|
65
103
|
end
|
66
104
|
|
67
105
|
private
|
68
106
|
def parse_segments(segments)
|
69
107
|
s = []
|
70
|
-
segments.
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
108
|
+
segments.each_with_index do |part, index|
|
109
|
+
case part
|
110
|
+
when Regin::Anchor
|
111
|
+
# ignore
|
112
|
+
when Regin::Character
|
113
|
+
throw :halt unless part.literal?
|
114
|
+
|
115
|
+
if s.last.is_a?(String)
|
116
|
+
s.last << part.value.dup
|
78
117
|
else
|
79
|
-
s <<
|
118
|
+
s << part.value.dup
|
80
119
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
if static.is_a?(String)
|
85
|
-
s << static.freeze
|
120
|
+
when Regin::Group
|
121
|
+
if part.name
|
122
|
+
s << DynamicSegment.new(part.name, part.expression.to_regexp(true))
|
86
123
|
else
|
87
|
-
|
124
|
+
s << parse_segments(part.expression)
|
88
125
|
end
|
126
|
+
when Regin::Expression
|
127
|
+
return parse_segments(part)
|
128
|
+
else
|
129
|
+
throw :halt
|
89
130
|
end
|
90
131
|
end
|
91
132
|
|
92
|
-
s
|
133
|
+
s
|
93
134
|
end
|
94
135
|
|
95
|
-
|
136
|
+
EMPTY_STRING = ''.freeze
|
137
|
+
|
138
|
+
def generate_from_segments(segments, params, merged, options, optional = false)
|
96
139
|
if optional
|
97
|
-
return
|
98
|
-
return
|
99
|
-
params
|
140
|
+
return EMPTY_STRING if segments.all? { |s| s.is_a?(String) }
|
141
|
+
return EMPTY_STRING unless segments.flatten.any? { |s|
|
142
|
+
params.has_key?(s.name) if s.is_a?(DynamicSegment)
|
100
143
|
}
|
101
|
-
return
|
144
|
+
return EMPTY_STRING if segments.any? { |segment|
|
102
145
|
if segment.is_a?(DynamicSegment)
|
103
|
-
value = merged[segment.name] || defaults[segment.name]
|
104
|
-
value =
|
105
|
-
|
106
|
-
merged_value = merged[segment.name]
|
107
|
-
merged_value = merged_value.to_param if merged_value.respond_to?(:to_param)
|
146
|
+
value = merged[segment.name] || @defaults[segment.name]
|
147
|
+
value = parameterize(segment.name, value, options)
|
108
148
|
|
109
|
-
|
110
|
-
default_value =
|
149
|
+
merged_value = parameterize(segment.name, merged[segment.name], options)
|
150
|
+
default_value = parameterize(segment.name, @defaults[segment.name], options)
|
111
151
|
|
112
152
|
if value.nil? || segment !~ value
|
113
153
|
true
|
114
154
|
elsif merged_value == default_value
|
115
155
|
# Nasty control flow
|
116
156
|
return :clear_remaining_segments
|
117
|
-
true
|
118
157
|
else
|
119
158
|
false
|
120
159
|
end
|
@@ -127,20 +166,20 @@ module Rack::Mount
|
|
127
166
|
when String
|
128
167
|
segment
|
129
168
|
when DynamicSegment
|
130
|
-
value = params[segment.name] || merged[segment.name] || defaults[segment.name]
|
131
|
-
value =
|
169
|
+
value = params[segment.name] || merged[segment.name] || @defaults[segment.name]
|
170
|
+
value = parameterize(segment.name, value, options)
|
132
171
|
if value && segment =~ value.to_s
|
133
172
|
value
|
134
173
|
else
|
135
174
|
return
|
136
175
|
end
|
137
176
|
when Array
|
138
|
-
value = generate_from_segments(segment, params, merged,
|
177
|
+
value = generate_from_segments(segment, params, merged, options, true)
|
139
178
|
if value == :clear_remaining_segments
|
140
179
|
segment.each { |s| params.delete(s.name) if s.is_a?(DynamicSegment) }
|
141
|
-
|
180
|
+
EMPTY_STRING
|
142
181
|
elsif value.nil?
|
143
|
-
|
182
|
+
EMPTY_STRING
|
144
183
|
else
|
145
184
|
value
|
146
185
|
end
|
@@ -152,6 +191,14 @@ module Rack::Mount
|
|
152
191
|
|
153
192
|
generated.join
|
154
193
|
end
|
194
|
+
|
195
|
+
def parameterize(name, value, options)
|
196
|
+
if block = options[:parameterize]
|
197
|
+
block.call(name, value)
|
198
|
+
else
|
199
|
+
value
|
200
|
+
end
|
201
|
+
end
|
155
202
|
end
|
156
203
|
include InstanceMethods
|
157
204
|
|
data/lib/rack/mount/multimap.rb
CHANGED
@@ -1,26 +1,14 @@
|
|
1
|
-
begin
|
2
|
-
require 'nested_multimap'
|
3
|
-
rescue LoadError
|
4
|
-
$: << File.expand_path(File.join(File.dirname(__FILE__), 'vendor/multimap'))
|
5
|
-
require 'nested_multimap'
|
6
|
-
end
|
7
|
-
|
8
1
|
module Rack::Mount
|
9
|
-
class Multimap
|
10
|
-
def self.[](*args)
|
11
|
-
map = super
|
12
|
-
map.instance_variable_set('@fuzz', {})
|
13
|
-
map
|
14
|
-
end
|
15
|
-
|
2
|
+
class Multimap #:nodoc:
|
16
3
|
def initialize(default = [])
|
17
|
-
@
|
18
|
-
super
|
4
|
+
@hash = Hash.new(default)
|
19
5
|
end
|
20
6
|
|
21
7
|
def initialize_copy(original)
|
22
|
-
@
|
23
|
-
|
8
|
+
@hash = Hash.new(original.default.dup)
|
9
|
+
original.hash.each_pair do |key, container|
|
10
|
+
@hash[key] = container.dup
|
11
|
+
end
|
24
12
|
end
|
25
13
|
|
26
14
|
def store(*args)
|
@@ -35,15 +23,14 @@ module Rack::Mount
|
|
35
23
|
end
|
36
24
|
|
37
25
|
if key.is_a?(Regexp)
|
38
|
-
@fuzz[value] = key
|
39
26
|
if keys.empty?
|
40
|
-
|
27
|
+
@hash.each_pair { |k, l| l << value if k =~ key }
|
41
28
|
self.default << value
|
42
29
|
else
|
43
|
-
|
30
|
+
@hash.each_pair { |k, _|
|
44
31
|
if k =~ key
|
45
32
|
args[0] = k
|
46
|
-
|
33
|
+
_store(*args)
|
47
34
|
end
|
48
35
|
}
|
49
36
|
|
@@ -51,19 +38,20 @@ module Rack::Mount
|
|
51
38
|
default[*keys.dup] = value
|
52
39
|
end
|
53
40
|
else
|
54
|
-
|
41
|
+
_store(*args)
|
55
42
|
end
|
56
43
|
end
|
57
44
|
alias_method :[]=, :store
|
58
45
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
46
|
+
def [](*keys)
|
47
|
+
i, l, r, k = 0, keys.length, self, self.class
|
48
|
+
while r.is_a?(k)
|
49
|
+
r = i < l ? r.hash[keys[i]] : r.default
|
50
|
+
i += 1
|
51
|
+
end
|
52
|
+
r
|
63
53
|
end
|
64
54
|
|
65
|
-
undef :index, :invert
|
66
|
-
|
67
55
|
def height
|
68
56
|
containers_with_default.max { |a, b| a.length <=> b.length }.length
|
69
57
|
end
|
@@ -73,20 +61,75 @@ module Rack::Mount
|
|
73
61
|
lengths.inject(0) { |sum, len| sum += len }.to_f / lengths.size
|
74
62
|
end
|
75
63
|
|
64
|
+
def containers_with_default
|
65
|
+
containers = []
|
66
|
+
each_container_with_default { |container| containers << container }
|
67
|
+
containers
|
68
|
+
end
|
69
|
+
|
76
70
|
protected
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
container
|
87
|
-
|
88
|
-
end
|
71
|
+
def _store(*args)
|
72
|
+
keys = args
|
73
|
+
value = args.pop
|
74
|
+
|
75
|
+
raise ArgumentError, 'wrong number of arguments (1 for 2)' unless value
|
76
|
+
|
77
|
+
if keys.length > 1
|
78
|
+
update_container(keys.shift) do |container|
|
79
|
+
container = self.class.new(container) unless container.is_a?(self.class)
|
80
|
+
container[*keys] = value
|
81
|
+
container
|
89
82
|
end
|
83
|
+
elsif keys.length == 1
|
84
|
+
update_container(keys.first) do |container|
|
85
|
+
container << value
|
86
|
+
container
|
87
|
+
end
|
88
|
+
else
|
89
|
+
self << value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def <<(value)
|
94
|
+
@hash.each_value { |container| container << value }
|
95
|
+
self.default << value
|
96
|
+
self
|
97
|
+
end
|
98
|
+
|
99
|
+
def each_container_with_default(&block)
|
100
|
+
@hash.each_value do |container|
|
101
|
+
iterate_over_container(container, &block)
|
102
|
+
end
|
103
|
+
iterate_over_container(default, &block)
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
def default
|
108
|
+
@hash.default
|
109
|
+
end
|
110
|
+
|
111
|
+
def default=(value)
|
112
|
+
@hash.default = value
|
113
|
+
end
|
114
|
+
|
115
|
+
def hash
|
116
|
+
@hash
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
def update_container(key)
|
121
|
+
container = @hash[key]
|
122
|
+
container = container.dup if container.equal?(default)
|
123
|
+
container = yield(container)
|
124
|
+
@hash[key] = container
|
125
|
+
end
|
126
|
+
|
127
|
+
def iterate_over_container(container)
|
128
|
+
if container.respond_to?(:each_container_with_default)
|
129
|
+
container.each_container_with_default do |value|
|
130
|
+
yield value
|
131
|
+
end
|
132
|
+
else
|
90
133
|
yield container
|
91
134
|
end
|
92
135
|
end
|
data/lib/rack/mount/prefix.rb
CHANGED
@@ -2,26 +2,31 @@ require 'rack/mount/utils'
|
|
2
2
|
|
3
3
|
module Rack::Mount
|
4
4
|
class Prefix #:nodoc:
|
5
|
+
EMPTY_STRING = ''.freeze
|
6
|
+
PATH_INFO = 'PATH_INFO'.freeze
|
7
|
+
SCRIPT_NAME = 'SCRIPT_NAME'.freeze
|
8
|
+
SLASH = '/'.freeze
|
9
|
+
|
5
10
|
KEY = 'rack.mount.prefix'.freeze
|
6
11
|
|
7
12
|
def initialize(app, prefix = nil)
|
8
|
-
@app, @prefix = app, prefix
|
13
|
+
@app, @prefix = app, prefix
|
9
14
|
freeze
|
10
15
|
end
|
11
16
|
|
12
17
|
def call(env)
|
13
18
|
if prefix = env[KEY] || @prefix
|
14
|
-
old_path_info = env[
|
15
|
-
old_script_name = env[
|
19
|
+
old_path_info = env[PATH_INFO].dup
|
20
|
+
old_script_name = env[SCRIPT_NAME].dup
|
16
21
|
|
17
22
|
begin
|
18
|
-
env[
|
19
|
-
env[
|
20
|
-
env[
|
23
|
+
env[PATH_INFO] = env[PATH_INFO].sub(prefix, EMPTY_STRING)
|
24
|
+
env[PATH_INFO] = EMPTY_STRING if env[PATH_INFO] == SLASH
|
25
|
+
env[SCRIPT_NAME] = Utils.normalize_path(env[SCRIPT_NAME].to_s + prefix)
|
21
26
|
@app.call(env)
|
22
27
|
ensure
|
23
|
-
env[
|
24
|
-
env[
|
28
|
+
env[PATH_INFO] = old_path_info
|
29
|
+
env[SCRIPT_NAME] = old_script_name
|
25
30
|
end
|
26
31
|
else
|
27
32
|
@app.call(env)
|
@@ -1,7 +1,9 @@
|
|
1
|
-
require 'rack/mount/utils'
|
2
|
-
|
3
1
|
module Rack::Mount
|
4
|
-
|
2
|
+
if Regin.regexp_supports_named_captures?
|
3
|
+
RegexpWithNamedGroups = Regexp
|
4
|
+
else
|
5
|
+
require 'strscan'
|
6
|
+
|
5
7
|
# A wrapper that adds shim named capture support to older
|
6
8
|
# versions of Ruby.
|
7
9
|
#
|
@@ -26,9 +28,25 @@ module Rack::Mount
|
|
26
28
|
|
27
29
|
# Wraps Regexp with named capture support.
|
28
30
|
def initialize(regexp)
|
29
|
-
regexp
|
31
|
+
regexp = Regexp.compile(regexp) unless regexp.is_a?(Regexp)
|
32
|
+
source, options = regexp.source, regexp.options
|
33
|
+
@names, scanner = [], StringScanner.new(source)
|
34
|
+
|
35
|
+
while scanner.skip_until(/\(/)
|
36
|
+
if scanner.scan(/\?:<([^>]+)>/)
|
37
|
+
@names << scanner[1]
|
38
|
+
elsif scanner.scan(/\?(i?m?x?\-?i?m?x?)?:/)
|
39
|
+
# ignore noncapture
|
40
|
+
else
|
41
|
+
@names << nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
source.gsub!(/\?:<([^>]+)>/, '')
|
45
|
+
|
46
|
+
@names = [] unless @names.any?
|
30
47
|
@names.freeze
|
31
|
-
|
48
|
+
|
49
|
+
super(source, options)
|
32
50
|
end
|
33
51
|
|
34
52
|
def names
|
@@ -42,8 +60,10 @@ module Rack::Mount
|
|
42
60
|
}
|
43
61
|
named_captures
|
44
62
|
end
|
63
|
+
|
64
|
+
def eql?(other)
|
65
|
+
super && @names.eql?(other.names)
|
66
|
+
end
|
45
67
|
end
|
46
|
-
else
|
47
|
-
RegexpWithNamedGroups = Regexp
|
48
68
|
end
|
49
69
|
end
|
data/lib/rack/mount/route.rb
CHANGED
@@ -9,11 +9,6 @@ module Rack::Mount
|
|
9
9
|
# new Route objects. Instead use the factory method, RouteSet#add_route
|
10
10
|
# to create new routes and add them to the set.
|
11
11
|
class Route
|
12
|
-
extend Mixover
|
13
|
-
|
14
|
-
# Include generation and recognition concerns
|
15
|
-
include Generation::Route, Recognition::Route
|
16
|
-
|
17
12
|
# Valid rack application to call if conditions are met
|
18
13
|
attr_reader :app
|
19
14
|
|
@@ -27,41 +22,103 @@ module Rack::Mount
|
|
27
22
|
# Symbol identifier for the route used with named route generations
|
28
23
|
attr_reader :name
|
29
24
|
|
30
|
-
|
31
|
-
@set = set
|
25
|
+
attr_reader :named_captures
|
32
26
|
|
27
|
+
def initialize(app, conditions, defaults, name)
|
33
28
|
unless app.respond_to?(:call)
|
34
29
|
raise ArgumentError, 'app must be a valid rack application' \
|
35
30
|
' and respond to call'
|
36
31
|
end
|
37
32
|
@app = app
|
38
33
|
|
39
|
-
@name = name.to_sym
|
34
|
+
@name = name ? name.to_sym : nil
|
40
35
|
@defaults = (defaults || {}).freeze
|
41
36
|
|
42
|
-
unless conditions.is_a?(Hash)
|
43
|
-
raise ArgumentError, 'conditions must be a Hash'
|
44
|
-
end
|
45
37
|
@conditions = {}
|
46
38
|
|
47
39
|
conditions.each do |method, pattern|
|
48
40
|
next unless method && pattern
|
49
41
|
|
50
|
-
|
51
|
-
|
52
|
-
|
42
|
+
pattern = Regexp.compile("\\A#{Regexp.escape(pattern)}\\Z") if pattern.is_a?(String)
|
43
|
+
|
44
|
+
if pattern.is_a?(Regexp)
|
45
|
+
pattern = Utils.normalize_extended_expression(pattern)
|
46
|
+
pattern = RegexpWithNamedGroups.new(pattern)
|
47
|
+
pattern.extend(GeneratableRegexp::InstanceMethods)
|
48
|
+
pattern.defaults = @defaults
|
53
49
|
end
|
54
50
|
|
55
|
-
pattern = Regexp.compile("\\A#{Regexp.escape(pattern)}\\Z") if pattern.is_a?(String)
|
56
|
-
pattern = Utils.normalize_extended_expression(pattern)
|
57
|
-
pattern = RegexpWithNamedGroups.new(pattern)
|
58
|
-
pattern.extend(GeneratableRegexp::InstanceMethods)
|
59
51
|
@conditions[method] = pattern.freeze
|
60
52
|
end
|
61
53
|
|
54
|
+
@named_captures = {}
|
55
|
+
@conditions.map { |method, condition|
|
56
|
+
next unless condition.respond_to?(:named_captures)
|
57
|
+
@named_captures[method] = Hash[condition.named_captures.map { |k, v|
|
58
|
+
[k.to_sym, v.last - 1]
|
59
|
+
}].freeze
|
60
|
+
}
|
61
|
+
@named_captures.freeze
|
62
|
+
|
63
|
+
@has_significant_params = @conditions.any? { |method, condition|
|
64
|
+
(condition.respond_to?(:required_params) && condition.required_params.any?) ||
|
65
|
+
(condition.respond_to?(:required_defaults) && condition.required_defaults.any?)
|
66
|
+
}
|
67
|
+
|
68
|
+
if @conditions.has_key?(:path_info) &&
|
69
|
+
!Utils.regexp_anchored?(@conditions[:path_info])
|
70
|
+
@prefix = true
|
71
|
+
@app = Prefix.new(@app)
|
72
|
+
else
|
73
|
+
@prefix = false
|
74
|
+
end
|
75
|
+
|
62
76
|
@conditions.freeze
|
63
77
|
end
|
64
78
|
|
79
|
+
def prefix?
|
80
|
+
@prefix
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def generation_keys
|
85
|
+
@conditions.inject({}) { |keys, (_, condition)|
|
86
|
+
if condition.respond_to?(:required_defaults)
|
87
|
+
keys.merge!(condition.required_defaults)
|
88
|
+
else
|
89
|
+
keys
|
90
|
+
end
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def significant_params?
|
95
|
+
@has_significant_params
|
96
|
+
end
|
97
|
+
|
98
|
+
def generate(method, params = {}, recall = {}, options = {})
|
99
|
+
if method.nil?
|
100
|
+
result = Hash[@conditions.map { |m, condition|
|
101
|
+
[m, condition.generate(params, recall, options)] if condition.respond_to?(:generate)
|
102
|
+
}]
|
103
|
+
return nil if result.values.compact.empty?
|
104
|
+
else
|
105
|
+
if condition = @conditions[method]
|
106
|
+
if condition.respond_to?(:generate)
|
107
|
+
result = condition.generate(params, recall, options)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
if result
|
113
|
+
@defaults.each do |key, value|
|
114
|
+
params.delete(key) if params[key] == value
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
result
|
119
|
+
end
|
120
|
+
|
121
|
+
|
65
122
|
def inspect #:nodoc:
|
66
123
|
"#<#{self.class.name} @app=#{@app.inspect} @conditions=#{@conditions.inspect} @defaults=#{@defaults.inspect} @name=#{@name.inspect}>"
|
67
124
|
end
|