actionpack 6.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (181) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +311 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +58 -0
  5. data/lib/abstract_controller.rb +27 -0
  6. data/lib/abstract_controller/asset_paths.rb +12 -0
  7. data/lib/abstract_controller/base.rb +267 -0
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/caching/fragments.rb +150 -0
  10. data/lib/abstract_controller/callbacks.rb +224 -0
  11. data/lib/abstract_controller/collector.rb +43 -0
  12. data/lib/abstract_controller/error.rb +6 -0
  13. data/lib/abstract_controller/helpers.rb +194 -0
  14. data/lib/abstract_controller/logger.rb +14 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +20 -0
  16. data/lib/abstract_controller/rendering.rb +127 -0
  17. data/lib/abstract_controller/translation.rb +32 -0
  18. data/lib/abstract_controller/url_for.rb +35 -0
  19. data/lib/action_controller.rb +67 -0
  20. data/lib/action_controller/api.rb +150 -0
  21. data/lib/action_controller/api/api_rendering.rb +16 -0
  22. data/lib/action_controller/base.rb +271 -0
  23. data/lib/action_controller/caching.rb +46 -0
  24. data/lib/action_controller/form_builder.rb +50 -0
  25. data/lib/action_controller/log_subscriber.rb +81 -0
  26. data/lib/action_controller/metal.rb +256 -0
  27. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  28. data/lib/action_controller/metal/conditional_get.rb +280 -0
  29. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  30. data/lib/action_controller/metal/cookies.rb +16 -0
  31. data/lib/action_controller/metal/data_streaming.rb +151 -0
  32. data/lib/action_controller/metal/default_headers.rb +17 -0
  33. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  34. data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
  35. data/lib/action_controller/metal/exceptions.rb +74 -0
  36. data/lib/action_controller/metal/flash.rb +61 -0
  37. data/lib/action_controller/metal/force_ssl.rb +58 -0
  38. data/lib/action_controller/metal/head.rb +60 -0
  39. data/lib/action_controller/metal/helpers.rb +122 -0
  40. data/lib/action_controller/metal/http_authentication.rb +518 -0
  41. data/lib/action_controller/metal/implicit_render.rb +63 -0
  42. data/lib/action_controller/metal/instrumentation.rb +105 -0
  43. data/lib/action_controller/metal/live.rb +314 -0
  44. data/lib/action_controller/metal/mime_responds.rb +324 -0
  45. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  46. data/lib/action_controller/metal/params_wrapper.rb +297 -0
  47. data/lib/action_controller/metal/redirecting.rb +133 -0
  48. data/lib/action_controller/metal/renderers.rb +181 -0
  49. data/lib/action_controller/metal/rendering.rb +122 -0
  50. data/lib/action_controller/metal/request_forgery_protection.rb +456 -0
  51. data/lib/action_controller/metal/rescue.rb +28 -0
  52. data/lib/action_controller/metal/streaming.rb +223 -0
  53. data/lib/action_controller/metal/strong_parameters.rb +1105 -0
  54. data/lib/action_controller/metal/testing.rb +16 -0
  55. data/lib/action_controller/metal/url_for.rb +58 -0
  56. data/lib/action_controller/railtie.rb +89 -0
  57. data/lib/action_controller/railties/helpers.rb +24 -0
  58. data/lib/action_controller/renderer.rb +130 -0
  59. data/lib/action_controller/template_assertions.rb +11 -0
  60. data/lib/action_controller/test_case.rb +626 -0
  61. data/lib/action_dispatch.rb +114 -0
  62. data/lib/action_dispatch/http/cache.rb +226 -0
  63. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  64. data/lib/action_dispatch/http/content_security_policy.rb +284 -0
  65. data/lib/action_dispatch/http/filter_parameters.rb +86 -0
  66. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  67. data/lib/action_dispatch/http/headers.rb +132 -0
  68. data/lib/action_dispatch/http/mime_negotiation.rb +177 -0
  69. data/lib/action_dispatch/http/mime_type.rb +350 -0
  70. data/lib/action_dispatch/http/mime_types.rb +50 -0
  71. data/lib/action_dispatch/http/parameter_filter.rb +12 -0
  72. data/lib/action_dispatch/http/parameters.rb +136 -0
  73. data/lib/action_dispatch/http/rack_cache.rb +63 -0
  74. data/lib/action_dispatch/http/request.rb +427 -0
  75. data/lib/action_dispatch/http/response.rb +534 -0
  76. data/lib/action_dispatch/http/upload.rb +92 -0
  77. data/lib/action_dispatch/http/url.rb +350 -0
  78. data/lib/action_dispatch/journey.rb +7 -0
  79. data/lib/action_dispatch/journey/formatter.rb +189 -0
  80. data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
  81. data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
  82. data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
  83. data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
  84. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  85. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  86. data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
  87. data/lib/action_dispatch/journey/nodes/node.rb +141 -0
  88. data/lib/action_dispatch/journey/parser.rb +199 -0
  89. data/lib/action_dispatch/journey/parser.y +50 -0
  90. data/lib/action_dispatch/journey/parser_extras.rb +31 -0
  91. data/lib/action_dispatch/journey/path/pattern.rb +203 -0
  92. data/lib/action_dispatch/journey/route.rb +204 -0
  93. data/lib/action_dispatch/journey/router.rb +153 -0
  94. data/lib/action_dispatch/journey/router/utils.rb +102 -0
  95. data/lib/action_dispatch/journey/routes.rb +81 -0
  96. data/lib/action_dispatch/journey/scanner.rb +71 -0
  97. data/lib/action_dispatch/journey/visitors.rb +268 -0
  98. data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
  99. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  100. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  101. data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
  102. data/lib/action_dispatch/middleware/callbacks.rb +34 -0
  103. data/lib/action_dispatch/middleware/cookies.rb +663 -0
  104. data/lib/action_dispatch/middleware/debug_exceptions.rb +185 -0
  105. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  106. data/lib/action_dispatch/middleware/debug_view.rb +68 -0
  107. data/lib/action_dispatch/middleware/exception_wrapper.rb +181 -0
  108. data/lib/action_dispatch/middleware/executor.rb +21 -0
  109. data/lib/action_dispatch/middleware/flash.rb +300 -0
  110. data/lib/action_dispatch/middleware/host_authorization.rb +103 -0
  111. data/lib/action_dispatch/middleware/public_exceptions.rb +61 -0
  112. data/lib/action_dispatch/middleware/reloader.rb +12 -0
  113. data/lib/action_dispatch/middleware/remote_ip.rb +181 -0
  114. data/lib/action_dispatch/middleware/request_id.rb +43 -0
  115. data/lib/action_dispatch/middleware/session/abstract_store.rb +92 -0
  116. data/lib/action_dispatch/middleware/session/cache_store.rb +54 -0
  117. data/lib/action_dispatch/middleware/session/cookie_store.rb +113 -0
  118. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +28 -0
  119. data/lib/action_dispatch/middleware/show_exceptions.rb +62 -0
  120. data/lib/action_dispatch/middleware/ssl.rb +150 -0
  121. data/lib/action_dispatch/middleware/stack.rb +148 -0
  122. data/lib/action_dispatch/middleware/static.rb +129 -0
  123. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  124. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +24 -0
  126. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +29 -0
  128. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +62 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +38 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  136. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +15 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +165 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  139. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  140. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  141. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  142. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
  143. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  144. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  145. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  146. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
  147. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  148. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  149. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +203 -0
  150. data/lib/action_dispatch/railtie.rb +58 -0
  151. data/lib/action_dispatch/request/session.rb +242 -0
  152. data/lib/action_dispatch/request/utils.rb +78 -0
  153. data/lib/action_dispatch/routing.rb +261 -0
  154. data/lib/action_dispatch/routing/endpoint.rb +17 -0
  155. data/lib/action_dispatch/routing/inspector.rb +274 -0
  156. data/lib/action_dispatch/routing/mapper.rb +2289 -0
  157. data/lib/action_dispatch/routing/polymorphic_routes.rb +351 -0
  158. data/lib/action_dispatch/routing/redirection.rb +201 -0
  159. data/lib/action_dispatch/routing/route_set.rb +887 -0
  160. data/lib/action_dispatch/routing/routes_proxy.rb +69 -0
  161. data/lib/action_dispatch/routing/url_for.rb +237 -0
  162. data/lib/action_dispatch/system_test_case.rb +168 -0
  163. data/lib/action_dispatch/system_testing/browser.rb +80 -0
  164. data/lib/action_dispatch/system_testing/driver.rb +68 -0
  165. data/lib/action_dispatch/system_testing/server.rb +31 -0
  166. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +97 -0
  167. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +33 -0
  168. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  169. data/lib/action_dispatch/testing/assertion_response.rb +47 -0
  170. data/lib/action_dispatch/testing/assertions.rb +24 -0
  171. data/lib/action_dispatch/testing/assertions/response.rb +106 -0
  172. data/lib/action_dispatch/testing/assertions/routing.rb +234 -0
  173. data/lib/action_dispatch/testing/integration.rb +659 -0
  174. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  175. data/lib/action_dispatch/testing/test_process.rb +50 -0
  176. data/lib/action_dispatch/testing/test_request.rb +71 -0
  177. data/lib/action_dispatch/testing/test_response.rb +25 -0
  178. data/lib/action_pack.rb +26 -0
  179. data/lib/action_pack/gem_version.rb +17 -0
  180. data/lib/action_pack/version.rb +10 -0
  181. metadata +329 -0
@@ -0,0 +1,50 @@
1
+ class ActionDispatch::Journey::Parser
2
+ options no_result_var
3
+ token SLASH LITERAL SYMBOL LPAREN RPAREN DOT STAR OR
4
+
5
+ rule
6
+ expressions
7
+ : expression expressions { Cat.new(val.first, val.last) }
8
+ | expression { val.first }
9
+ | or
10
+ ;
11
+ expression
12
+ : terminal
13
+ | group
14
+ | star
15
+ ;
16
+ group
17
+ : LPAREN expressions RPAREN { Group.new(val[1]) }
18
+ ;
19
+ or
20
+ : expression OR expression { Or.new([val.first, val.last]) }
21
+ | expression OR or { Or.new([val.first, val.last]) }
22
+ ;
23
+ star
24
+ : STAR { Star.new(Symbol.new(val.last)) }
25
+ ;
26
+ terminal
27
+ : symbol
28
+ | literal
29
+ | slash
30
+ | dot
31
+ ;
32
+ slash
33
+ : SLASH { Slash.new(val.first) }
34
+ ;
35
+ symbol
36
+ : SYMBOL { Symbol.new(val.first) }
37
+ ;
38
+ literal
39
+ : LITERAL { Literal.new(val.first) }
40
+ ;
41
+ dot
42
+ : DOT { Dot.new(val.first) }
43
+ ;
44
+
45
+ end
46
+
47
+ ---- header
48
+ # :stopdoc:
49
+
50
+ require "action_dispatch/journey/parser_extras"
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "action_dispatch/journey/scanner"
4
+ require "action_dispatch/journey/nodes/node"
5
+
6
+ module ActionDispatch
7
+ # :stopdoc:
8
+ module Journey
9
+ class Parser < Racc::Parser
10
+ include Journey::Nodes
11
+
12
+ def self.parse(string)
13
+ new.parse string
14
+ end
15
+
16
+ def initialize
17
+ @scanner = Scanner.new
18
+ end
19
+
20
+ def parse(string)
21
+ @scanner.scan_setup(string)
22
+ do_parse
23
+ end
24
+
25
+ def next_token
26
+ @scanner.next_token
27
+ end
28
+ end
29
+ end
30
+ # :startdoc:
31
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module Journey # :nodoc:
5
+ module Path # :nodoc:
6
+ class Pattern # :nodoc:
7
+ attr_reader :spec, :requirements, :anchored
8
+
9
+ def self.from_string(string)
10
+ build(string, {}, "/.?", true)
11
+ end
12
+
13
+ def self.build(path, requirements, separators, anchored)
14
+ parser = Journey::Parser.new
15
+ ast = parser.parse path
16
+ new ast, requirements, separators, anchored
17
+ end
18
+
19
+ def initialize(ast, requirements, separators, anchored)
20
+ @spec = ast
21
+ @requirements = requirements
22
+ @separators = separators
23
+ @anchored = anchored
24
+
25
+ @names = nil
26
+ @optional_names = nil
27
+ @required_names = nil
28
+ @re = nil
29
+ @offsets = nil
30
+ end
31
+
32
+ def build_formatter
33
+ Visitors::FormatBuilder.new.accept(spec)
34
+ end
35
+
36
+ def eager_load!
37
+ required_names
38
+ offsets
39
+ to_regexp
40
+ nil
41
+ end
42
+
43
+ def ast
44
+ @spec.find_all(&:symbol?).each do |node|
45
+ re = @requirements[node.to_sym]
46
+ node.regexp = re if re
47
+ end
48
+
49
+ @spec.find_all(&:star?).each do |node|
50
+ node = node.left
51
+ node.regexp = @requirements[node.to_sym] || /(.+)/
52
+ end
53
+
54
+ @spec
55
+ end
56
+
57
+ def names
58
+ @names ||= spec.find_all(&:symbol?).map(&:name)
59
+ end
60
+
61
+ def required_names
62
+ @required_names ||= names - optional_names
63
+ end
64
+
65
+ def optional_names
66
+ @optional_names ||= spec.find_all(&:group?).flat_map { |group|
67
+ group.find_all(&:symbol?)
68
+ }.map(&:name).uniq
69
+ end
70
+
71
+ class AnchoredRegexp < Journey::Visitors::Visitor # :nodoc:
72
+ def initialize(separator, matchers)
73
+ @separator = separator
74
+ @matchers = matchers
75
+ @separator_re = "([^#{separator}]+)"
76
+ super()
77
+ end
78
+
79
+ def accept(node)
80
+ %r{\A#{visit node}\Z}
81
+ end
82
+
83
+ def visit_CAT(node)
84
+ [visit(node.left), visit(node.right)].join
85
+ end
86
+
87
+ def visit_SYMBOL(node)
88
+ node = node.to_sym
89
+
90
+ return @separator_re unless @matchers.key?(node)
91
+
92
+ re = @matchers[node]
93
+ "(#{Regexp.union(re)})"
94
+ end
95
+
96
+ def visit_GROUP(node)
97
+ "(?:#{visit node.left})?"
98
+ end
99
+
100
+ def visit_LITERAL(node)
101
+ Regexp.escape(node.left)
102
+ end
103
+ alias :visit_DOT :visit_LITERAL
104
+
105
+ def visit_SLASH(node)
106
+ node.left
107
+ end
108
+
109
+ def visit_STAR(node)
110
+ re = @matchers[node.left.to_sym] || ".+"
111
+ "(#{re})"
112
+ end
113
+
114
+ def visit_OR(node)
115
+ children = node.children.map { |n| visit n }
116
+ "(?:#{children.join(?|)})"
117
+ end
118
+ end
119
+
120
+ class UnanchoredRegexp < AnchoredRegexp # :nodoc:
121
+ def accept(node)
122
+ path = visit node
123
+ path == "/" ? %r{\A/} : %r{\A#{path}(?:\b|\Z|/)}
124
+ end
125
+ end
126
+
127
+ class MatchData # :nodoc:
128
+ attr_reader :names
129
+
130
+ def initialize(names, offsets, match)
131
+ @names = names
132
+ @offsets = offsets
133
+ @match = match
134
+ end
135
+
136
+ def captures
137
+ Array.new(length - 1) { |i| self[i + 1] }
138
+ end
139
+
140
+ def named_captures
141
+ @names.zip(captures).to_h
142
+ end
143
+
144
+ def [](x)
145
+ idx = @offsets[x - 1] + x
146
+ @match[idx]
147
+ end
148
+
149
+ def length
150
+ @offsets.length
151
+ end
152
+
153
+ def post_match
154
+ @match.post_match
155
+ end
156
+
157
+ def to_s
158
+ @match.to_s
159
+ end
160
+ end
161
+
162
+ def match(other)
163
+ return unless match = to_regexp.match(other)
164
+ MatchData.new(names, offsets, match)
165
+ end
166
+ alias :=~ :match
167
+
168
+ def source
169
+ to_regexp.source
170
+ end
171
+
172
+ def to_regexp
173
+ @re ||= regexp_visitor.new(@separators, @requirements).accept spec
174
+ end
175
+
176
+ private
177
+
178
+ def regexp_visitor
179
+ @anchored ? AnchoredRegexp : UnanchoredRegexp
180
+ end
181
+
182
+ def offsets
183
+ return @offsets if @offsets
184
+
185
+ @offsets = [0]
186
+
187
+ spec.find_all(&:symbol?).each do |node|
188
+ node = node.to_sym
189
+
190
+ if @requirements.key?(node)
191
+ re = /#{Regexp.union(@requirements[node])}|/
192
+ @offsets.push((re.match("").length - 1) + @offsets.last)
193
+ else
194
+ @offsets << @offsets.last
195
+ end
196
+ end
197
+
198
+ @offsets
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,204 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ # :stopdoc:
5
+ module Journey
6
+ class Route
7
+ attr_reader :app, :path, :defaults, :name, :precedence, :constraints,
8
+ :internal, :scope_options
9
+
10
+ alias :conditions :constraints
11
+
12
+ module VerbMatchers
13
+ VERBS = %w{ DELETE GET HEAD OPTIONS LINK PATCH POST PUT TRACE UNLINK }
14
+ VERBS.each do |v|
15
+ class_eval <<-eoc, __FILE__, __LINE__ + 1
16
+ class #{v}
17
+ def self.verb; name.split("::").last; end
18
+ def self.call(req); req.#{v.downcase}?; end
19
+ end
20
+ eoc
21
+ end
22
+
23
+ class Unknown
24
+ attr_reader :verb
25
+
26
+ def initialize(verb)
27
+ @verb = verb
28
+ end
29
+
30
+ def call(request); @verb === request.request_method; end
31
+ end
32
+
33
+ class All
34
+ def self.call(_); true; end
35
+ def self.verb; ""; end
36
+ end
37
+
38
+ VERB_TO_CLASS = VERBS.each_with_object(all: All) do |verb, hash|
39
+ klass = const_get verb
40
+ hash[verb] = klass
41
+ hash[verb.downcase] = klass
42
+ hash[verb.downcase.to_sym] = klass
43
+ end
44
+ end
45
+
46
+ def self.verb_matcher(verb)
47
+ VerbMatchers::VERB_TO_CLASS.fetch(verb) do
48
+ VerbMatchers::Unknown.new verb.to_s.dasherize.upcase
49
+ end
50
+ end
51
+
52
+ def self.build(name, app, path, constraints, required_defaults, defaults)
53
+ request_method_match = verb_matcher(constraints.delete(:request_method))
54
+ new name, app, path, constraints, required_defaults, defaults, request_method_match, 0, {}
55
+ end
56
+
57
+ ##
58
+ # +path+ is a path constraint.
59
+ # +constraints+ is a hash of constraints to be applied to this route.
60
+ def initialize(name, app, path, constraints, required_defaults, defaults, request_method_match, precedence, scope_options, internal = false)
61
+ @name = name
62
+ @app = app
63
+ @path = path
64
+
65
+ @request_method_match = request_method_match
66
+ @constraints = constraints
67
+ @defaults = defaults
68
+ @required_defaults = nil
69
+ @_required_defaults = required_defaults
70
+ @required_parts = nil
71
+ @parts = nil
72
+ @decorated_ast = nil
73
+ @precedence = precedence
74
+ @path_formatter = @path.build_formatter
75
+ @scope_options = scope_options
76
+ @internal = internal
77
+ end
78
+
79
+ def eager_load!
80
+ path.eager_load!
81
+ ast
82
+ parts
83
+ required_defaults
84
+ nil
85
+ end
86
+
87
+ def ast
88
+ @decorated_ast ||= begin
89
+ decorated_ast = path.ast
90
+ decorated_ast.find_all(&:terminal?).each { |n| n.memo = self }
91
+ decorated_ast
92
+ end
93
+ end
94
+
95
+ # Needed for `rails routes`. Picks up succinctly defined requirements
96
+ # for a route, for example route
97
+ #
98
+ # get 'photo/:id', :controller => 'photos', :action => 'show',
99
+ # :id => /[A-Z]\d{5}/
100
+ #
101
+ # will have {:controller=>"photos", :action=>"show", :id=>/[A-Z]\d{5}/}
102
+ # as requirements.
103
+ def requirements
104
+ @defaults.merge(path.requirements).delete_if { |_, v|
105
+ /.+?/ == v
106
+ }
107
+ end
108
+
109
+ def segments
110
+ path.names
111
+ end
112
+
113
+ def required_keys
114
+ required_parts + required_defaults.keys
115
+ end
116
+
117
+ def score(supplied_keys)
118
+ required_keys = path.required_names
119
+
120
+ required_keys.each do |k|
121
+ return -1 unless supplied_keys.include?(k)
122
+ end
123
+
124
+ score = 0
125
+ path.names.each do |k|
126
+ score += 1 if supplied_keys.include?(k)
127
+ end
128
+
129
+ score + (required_defaults.length * 2)
130
+ end
131
+
132
+ def parts
133
+ @parts ||= segments.map(&:to_sym)
134
+ end
135
+ alias :segment_keys :parts
136
+
137
+ def format(path_options)
138
+ @path_formatter.evaluate path_options
139
+ end
140
+
141
+ def required_parts
142
+ @required_parts ||= path.required_names.map(&:to_sym)
143
+ end
144
+
145
+ def required_default?(key)
146
+ @_required_defaults.include?(key)
147
+ end
148
+
149
+ def required_defaults
150
+ @required_defaults ||= @defaults.dup.delete_if do |k, _|
151
+ parts.include?(k) || !required_default?(k)
152
+ end
153
+ end
154
+
155
+ def glob?
156
+ !path.spec.grep(Nodes::Star).empty?
157
+ end
158
+
159
+ def dispatcher?
160
+ @app.dispatcher?
161
+ end
162
+
163
+ def matches?(request)
164
+ match_verb(request) &&
165
+ constraints.all? { |method, value|
166
+ case value
167
+ when Regexp, String
168
+ value === request.send(method).to_s
169
+ when Array
170
+ value.include?(request.send(method))
171
+ when TrueClass
172
+ request.send(method).present?
173
+ when FalseClass
174
+ request.send(method).blank?
175
+ else
176
+ value === request.send(method)
177
+ end
178
+ }
179
+ end
180
+
181
+ def ip
182
+ constraints[:ip] || //
183
+ end
184
+
185
+ def requires_matching_verb?
186
+ !@request_method_match.all? { |x| x == VerbMatchers::All }
187
+ end
188
+
189
+ def verb
190
+ verbs.join("|")
191
+ end
192
+
193
+ private
194
+ def verbs
195
+ @request_method_match.map(&:verb)
196
+ end
197
+
198
+ def match_verb(request)
199
+ @request_method_match.any? { |m| m.call request }
200
+ end
201
+ end
202
+ end
203
+ # :startdoc:
204
+ end